1
0
mirror of https://github.com/FFmpeg/FFmpeg.git synced 2024-12-12 19:18:44 +02:00
FFmpeg/libavfilter/vsrc_testsrc.c

2250 lines
75 KiB
C
Raw Normal View History

2011-06-18 04:11:16 +03:00
/*
* Copyright (c) 2007 Nicolas George <nicolas.george@normalesup.org>
* Copyright (c) 2011 Stefano Sabatini
* Copyright (c) 2012 Paul B Mahol
2011-06-18 04:11:16 +03:00
*
* 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
* Misc test sources.
*
* testsrc is based on the test pattern generator demuxer by Nicolas George:
* http://lists.ffmpeg.org/pipermail/ffmpeg-devel/2007-October/037845.html
*
* rgbtestsrc is ported from MPlayer libmpcodecs/vf_rgbtest.c by
* Michael Niedermayer.
*
* allyuv, smptebars and smptehdbars are by Paul B Mahol.
2011-06-18 04:11:16 +03:00
*/
#include "config_components.h"
2011-06-18 04:11:16 +03:00
#include <float.h>
#include "libavutil/avassert.h"
#include "libavutil/common.h"
#include "libavutil/ffmath.h"
2011-06-18 04:11:16 +03:00
#include "libavutil/opt.h"
#include "libavutil/imgutils.h"
#include "libavutil/intreadwrite.h"
2011-06-18 04:11:16 +03:00
#include "libavutil/parseutils.h"
#include "libavutil/xga_font_data.h"
2011-06-18 04:11:16 +03:00
#include "avfilter.h"
#include "drawutils.h"
#include "filters.h"
#include "formats.h"
#include "internal.h"
#include "video.h"
2011-06-18 04:11:16 +03:00
2014-04-11 12:54:15 +03:00
typedef struct TestSourceContext {
2011-06-18 04:11:16 +03:00
const AVClass *class;
int w, h;
2022-04-10 19:12:53 +02:00
int pw, ph;
2011-06-18 04:11:16 +03:00
unsigned int nb_frame;
2012-08-16 22:53:30 +03:00
AVRational time_base, frame_rate;
int64_t pts;
int64_t duration; ///< duration expressed in microseconds
AVRational sar; ///< sample aspect ratio
int draw_once; ///< draw only the first frame, always put out the same picture
int draw_once_reset; ///< draw only the first frame or in case of reset
Merge commit '7e350379f87e7f74420b4813170fe808e2313911' * commit '7e350379f87e7f74420b4813170fe808e2313911': lavfi: switch to AVFrame. Conflicts: doc/filters.texi libavfilter/af_ashowinfo.c libavfilter/audio.c libavfilter/avfilter.c libavfilter/avfilter.h libavfilter/buffersink.c libavfilter/buffersrc.c libavfilter/buffersrc.h libavfilter/f_select.c libavfilter/f_setpts.c libavfilter/fifo.c libavfilter/split.c libavfilter/src_movie.c libavfilter/version.h libavfilter/vf_aspect.c libavfilter/vf_bbox.c libavfilter/vf_blackframe.c libavfilter/vf_delogo.c libavfilter/vf_drawbox.c libavfilter/vf_drawtext.c libavfilter/vf_fade.c libavfilter/vf_fieldorder.c libavfilter/vf_fps.c libavfilter/vf_frei0r.c libavfilter/vf_gradfun.c libavfilter/vf_hqdn3d.c libavfilter/vf_lut.c libavfilter/vf_overlay.c libavfilter/vf_pad.c libavfilter/vf_scale.c libavfilter/vf_showinfo.c libavfilter/vf_transpose.c libavfilter/vf_vflip.c libavfilter/vf_yadif.c libavfilter/video.c libavfilter/vsrc_testsrc.c libavfilter/yadif.h Following are notes about the merge authorship and various technical details. Michael Niedermayer: * Main merge operation, notably avfilter.c and video.c * Switch to AVFrame: - afade - anullsrc - apad - aresample - blackframe - deshake - idet - il - mandelbrot - mptestsrc - noise - setfield - smartblur - tinterlace * various merge changes and fixes in: - ashowinfo - blackdetect - field - fps - select - testsrc - yadif Nicolas George: * Switch to AVFrame: - make rawdec work with refcounted frames. Adapted from commit 759001c534287a96dc96d1e274665feb7059145d by Anton Khirnov. Also, fix the use of || instead of | in a flags check. - make buffer sink and src, audio and video work all together Clément Bœsch: * Switch to AVFrame: - aevalsrc - alphaextract - blend - cellauto - colormatrix - concat - earwax - ebur128 - edgedetect - geq - histeq - histogram - hue - kerndeint - life - movie - mp (with the help of Michael) - overlay - pad - pan - pp - pp - removelogo - sendcmd - showspectrum - showwaves - silencedetect - stereo3d - subtitles - super2xsai - swapuv - thumbnail - tile Hendrik Leppkes: * Switch to AVFrame: - aconvert - amerge - asetnsamples - atempo - biquads Matthieu Bouron: * Switch to AVFrame - alphamerge - decimate - volumedetect Stefano Sabatini: * Switch to AVFrame: - astreamsync - flite - framestep Signed-off-by: Michael Niedermayer <michaelni@gmx.at> Signed-off-by: Nicolas George <nicolas.george@normalesup.org> Signed-off-by: Clément Bœsch <ubitux@gmail.com> Signed-off-by: Hendrik Leppkes <h.leppkes@gmail.com> Signed-off-by: Matthieu Bouron <matthieu.bouron@gmail.com> Signed-off-by: Stefano Sabatini <stefasab@gmail.com> Merged-by: Michael Niedermayer <michaelni@gmx.at>
2013-03-10 03:30:30 +03:00
AVFrame *picref; ///< cached reference containing the painted picture
void (* fill_picture_fn)(AVFilterContext *ctx, AVFrame *frame);
/* only used by testsrc */
int nb_decimals;
/* only used by testsrc2 */
int alpha;
/* only used by colorspectrum */
int type;
/* only used by color */
FFDrawContext draw;
FFDrawColor color;
uint8_t color_rgba[4];
/* only used by rgbtest */
uint8_t rgba_map[4];
int complement;
int depth;
2013-05-23 11:13:35 +03:00
/* only used by haldclut */
int level;
/* only used by zoneplate */
int k0, kx, ky, kt;
int kxt, kyt, kxy;
int kx2, ky2, kt2;
int xo, yo, to, kU, kV;
int lut_precision;
uint8_t *lut;
int (*fill_slice_fn)(AVFilterContext *ctx, void *arg, int job, int nb_jobs);
2011-06-18 04:11:16 +03:00
} TestSourceContext;
#define OFFSET(x) offsetof(TestSourceContext, x)
#define FLAGS AV_OPT_FLAG_VIDEO_PARAM|AV_OPT_FLAG_FILTERING_PARAM
#define FLAGSR AV_OPT_FLAG_VIDEO_PARAM|AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_RUNTIME_PARAM
2011-06-18 04:11:16 +03:00
2013-05-23 11:13:35 +03:00
#define SIZE_OPTIONS \
{ "size", "set video size", OFFSET(w), AV_OPT_TYPE_IMAGE_SIZE, {.str = "320x240"}, 0, 0, FLAGS },\
{ "s", "set video size", OFFSET(w), AV_OPT_TYPE_IMAGE_SIZE, {.str = "320x240"}, 0, 0, FLAGS },\
2013-05-23 11:13:35 +03:00
#define COMMON_OPTIONS_NOSIZE \
{ "rate", "set video rate", OFFSET(frame_rate), AV_OPT_TYPE_VIDEO_RATE, {.str = "25"}, 0, INT_MAX, FLAGS },\
{ "r", "set video rate", OFFSET(frame_rate), AV_OPT_TYPE_VIDEO_RATE, {.str = "25"}, 0, INT_MAX, FLAGS },\
{ "duration", "set video duration", OFFSET(duration), AV_OPT_TYPE_DURATION, {.i64 = -1}, -1, INT64_MAX, FLAGS },\
{ "d", "set video duration", OFFSET(duration), AV_OPT_TYPE_DURATION, {.i64 = -1}, -1, INT64_MAX, FLAGS },\
{ "sar", "set video sample aspect ratio", OFFSET(sar), AV_OPT_TYPE_RATIONAL, {.dbl= 1}, 0, INT_MAX, FLAGS },
2012-07-29 17:12:24 +03:00
2013-05-23 11:13:35 +03:00
#define COMMON_OPTIONS SIZE_OPTIONS COMMON_OPTIONS_NOSIZE
#define NOSIZE_OPTIONS_OFFSET 2
/* Filters using COMMON_OPTIONS_NOSIZE also use the following options
* via &options[NOSIZE_OPTIONS_OFFSET]. So don't break it. */
static const AVOption options[] = {
COMMON_OPTIONS
{ NULL }
2011-06-18 04:11:16 +03:00
};
static av_cold int init(AVFilterContext *ctx)
2011-06-18 04:11:16 +03:00
{
TestSourceContext *test = ctx->priv;
2012-08-16 22:53:30 +03:00
test->time_base = av_inv_q(test->frame_rate);
2011-06-18 04:11:16 +03:00
test->nb_frame = 0;
test->pts = 0;
av_log(ctx, AV_LOG_VERBOSE, "size:%dx%d rate:%d/%d duration:%f sar:%d/%d\n",
2012-08-16 22:53:30 +03:00
test->w, test->h, test->frame_rate.num, test->frame_rate.den,
test->duration < 0 ? -1 : (double)test->duration/1000000,
test->sar.num, test->sar.den);
2011-06-18 04:11:16 +03:00
return 0;
}
static av_cold void uninit(AVFilterContext *ctx)
{
TestSourceContext *test = ctx->priv;
Merge commit '7e350379f87e7f74420b4813170fe808e2313911' * commit '7e350379f87e7f74420b4813170fe808e2313911': lavfi: switch to AVFrame. Conflicts: doc/filters.texi libavfilter/af_ashowinfo.c libavfilter/audio.c libavfilter/avfilter.c libavfilter/avfilter.h libavfilter/buffersink.c libavfilter/buffersrc.c libavfilter/buffersrc.h libavfilter/f_select.c libavfilter/f_setpts.c libavfilter/fifo.c libavfilter/split.c libavfilter/src_movie.c libavfilter/version.h libavfilter/vf_aspect.c libavfilter/vf_bbox.c libavfilter/vf_blackframe.c libavfilter/vf_delogo.c libavfilter/vf_drawbox.c libavfilter/vf_drawtext.c libavfilter/vf_fade.c libavfilter/vf_fieldorder.c libavfilter/vf_fps.c libavfilter/vf_frei0r.c libavfilter/vf_gradfun.c libavfilter/vf_hqdn3d.c libavfilter/vf_lut.c libavfilter/vf_overlay.c libavfilter/vf_pad.c libavfilter/vf_scale.c libavfilter/vf_showinfo.c libavfilter/vf_transpose.c libavfilter/vf_vflip.c libavfilter/vf_yadif.c libavfilter/video.c libavfilter/vsrc_testsrc.c libavfilter/yadif.h Following are notes about the merge authorship and various technical details. Michael Niedermayer: * Main merge operation, notably avfilter.c and video.c * Switch to AVFrame: - afade - anullsrc - apad - aresample - blackframe - deshake - idet - il - mandelbrot - mptestsrc - noise - setfield - smartblur - tinterlace * various merge changes and fixes in: - ashowinfo - blackdetect - field - fps - select - testsrc - yadif Nicolas George: * Switch to AVFrame: - make rawdec work with refcounted frames. Adapted from commit 759001c534287a96dc96d1e274665feb7059145d by Anton Khirnov. Also, fix the use of || instead of | in a flags check. - make buffer sink and src, audio and video work all together Clément Bœsch: * Switch to AVFrame: - aevalsrc - alphaextract - blend - cellauto - colormatrix - concat - earwax - ebur128 - edgedetect - geq - histeq - histogram - hue - kerndeint - life - movie - mp (with the help of Michael) - overlay - pad - pan - pp - pp - removelogo - sendcmd - showspectrum - showwaves - silencedetect - stereo3d - subtitles - super2xsai - swapuv - thumbnail - tile Hendrik Leppkes: * Switch to AVFrame: - aconvert - amerge - asetnsamples - atempo - biquads Matthieu Bouron: * Switch to AVFrame - alphamerge - decimate - volumedetect Stefano Sabatini: * Switch to AVFrame: - astreamsync - flite - framestep Signed-off-by: Michael Niedermayer <michaelni@gmx.at> Signed-off-by: Nicolas George <nicolas.george@normalesup.org> Signed-off-by: Clément Bœsch <ubitux@gmail.com> Signed-off-by: Hendrik Leppkes <h.leppkes@gmail.com> Signed-off-by: Matthieu Bouron <matthieu.bouron@gmail.com> Signed-off-by: Stefano Sabatini <stefasab@gmail.com> Merged-by: Michael Niedermayer <michaelni@gmx.at>
2013-03-10 03:30:30 +03:00
av_frame_free(&test->picref);
av_freep(&test->lut);
}
2011-06-18 04:11:16 +03:00
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;
2012-08-16 22:53:30 +03:00
outlink->frame_rate = test->frame_rate;
outlink->time_base = test->time_base;
2011-06-18 04:11:16 +03:00
return 0;
}
static int activate(AVFilterContext *ctx)
{
AVFilterLink *outlink = ctx->outputs[0];
TestSourceContext *test = ctx->priv;
AVFrame *frame;
if (!ff_outlink_frame_wanted(outlink))
return FFERROR_NOT_READY;
if (test->duration >= 0 &&
av_rescale_q(test->pts, test->time_base, AV_TIME_BASE_Q) >= test->duration) {
ff_outlink_set_status(outlink, AVERROR_EOF, test->pts);
return 0;
}
if (test->draw_once) {
if (test->draw_once_reset) {
av_frame_free(&test->picref);
test->draw_once_reset = 0;
}
if (!test->picref) {
test->picref =
Merge commit '7e350379f87e7f74420b4813170fe808e2313911' * commit '7e350379f87e7f74420b4813170fe808e2313911': lavfi: switch to AVFrame. Conflicts: doc/filters.texi libavfilter/af_ashowinfo.c libavfilter/audio.c libavfilter/avfilter.c libavfilter/avfilter.h libavfilter/buffersink.c libavfilter/buffersrc.c libavfilter/buffersrc.h libavfilter/f_select.c libavfilter/f_setpts.c libavfilter/fifo.c libavfilter/split.c libavfilter/src_movie.c libavfilter/version.h libavfilter/vf_aspect.c libavfilter/vf_bbox.c libavfilter/vf_blackframe.c libavfilter/vf_delogo.c libavfilter/vf_drawbox.c libavfilter/vf_drawtext.c libavfilter/vf_fade.c libavfilter/vf_fieldorder.c libavfilter/vf_fps.c libavfilter/vf_frei0r.c libavfilter/vf_gradfun.c libavfilter/vf_hqdn3d.c libavfilter/vf_lut.c libavfilter/vf_overlay.c libavfilter/vf_pad.c libavfilter/vf_scale.c libavfilter/vf_showinfo.c libavfilter/vf_transpose.c libavfilter/vf_vflip.c libavfilter/vf_yadif.c libavfilter/video.c libavfilter/vsrc_testsrc.c libavfilter/yadif.h Following are notes about the merge authorship and various technical details. Michael Niedermayer: * Main merge operation, notably avfilter.c and video.c * Switch to AVFrame: - afade - anullsrc - apad - aresample - blackframe - deshake - idet - il - mandelbrot - mptestsrc - noise - setfield - smartblur - tinterlace * various merge changes and fixes in: - ashowinfo - blackdetect - field - fps - select - testsrc - yadif Nicolas George: * Switch to AVFrame: - make rawdec work with refcounted frames. Adapted from commit 759001c534287a96dc96d1e274665feb7059145d by Anton Khirnov. Also, fix the use of || instead of | in a flags check. - make buffer sink and src, audio and video work all together Clément Bœsch: * Switch to AVFrame: - aevalsrc - alphaextract - blend - cellauto - colormatrix - concat - earwax - ebur128 - edgedetect - geq - histeq - histogram - hue - kerndeint - life - movie - mp (with the help of Michael) - overlay - pad - pan - pp - pp - removelogo - sendcmd - showspectrum - showwaves - silencedetect - stereo3d - subtitles - super2xsai - swapuv - thumbnail - tile Hendrik Leppkes: * Switch to AVFrame: - aconvert - amerge - asetnsamples - atempo - biquads Matthieu Bouron: * Switch to AVFrame - alphamerge - decimate - volumedetect Stefano Sabatini: * Switch to AVFrame: - astreamsync - flite - framestep Signed-off-by: Michael Niedermayer <michaelni@gmx.at> Signed-off-by: Nicolas George <nicolas.george@normalesup.org> Signed-off-by: Clément Bœsch <ubitux@gmail.com> Signed-off-by: Hendrik Leppkes <h.leppkes@gmail.com> Signed-off-by: Matthieu Bouron <matthieu.bouron@gmail.com> Signed-off-by: Stefano Sabatini <stefasab@gmail.com> Merged-by: Michael Niedermayer <michaelni@gmx.at>
2013-03-10 03:30:30 +03:00
ff_get_video_buffer(outlink, test->w, test->h);
if (!test->picref)
return AVERROR(ENOMEM);
test->fill_picture_fn(outlink->src, test->picref);
}
Merge commit '7e350379f87e7f74420b4813170fe808e2313911' * commit '7e350379f87e7f74420b4813170fe808e2313911': lavfi: switch to AVFrame. Conflicts: doc/filters.texi libavfilter/af_ashowinfo.c libavfilter/audio.c libavfilter/avfilter.c libavfilter/avfilter.h libavfilter/buffersink.c libavfilter/buffersrc.c libavfilter/buffersrc.h libavfilter/f_select.c libavfilter/f_setpts.c libavfilter/fifo.c libavfilter/split.c libavfilter/src_movie.c libavfilter/version.h libavfilter/vf_aspect.c libavfilter/vf_bbox.c libavfilter/vf_blackframe.c libavfilter/vf_delogo.c libavfilter/vf_drawbox.c libavfilter/vf_drawtext.c libavfilter/vf_fade.c libavfilter/vf_fieldorder.c libavfilter/vf_fps.c libavfilter/vf_frei0r.c libavfilter/vf_gradfun.c libavfilter/vf_hqdn3d.c libavfilter/vf_lut.c libavfilter/vf_overlay.c libavfilter/vf_pad.c libavfilter/vf_scale.c libavfilter/vf_showinfo.c libavfilter/vf_transpose.c libavfilter/vf_vflip.c libavfilter/vf_yadif.c libavfilter/video.c libavfilter/vsrc_testsrc.c libavfilter/yadif.h Following are notes about the merge authorship and various technical details. Michael Niedermayer: * Main merge operation, notably avfilter.c and video.c * Switch to AVFrame: - afade - anullsrc - apad - aresample - blackframe - deshake - idet - il - mandelbrot - mptestsrc - noise - setfield - smartblur - tinterlace * various merge changes and fixes in: - ashowinfo - blackdetect - field - fps - select - testsrc - yadif Nicolas George: * Switch to AVFrame: - make rawdec work with refcounted frames. Adapted from commit 759001c534287a96dc96d1e274665feb7059145d by Anton Khirnov. Also, fix the use of || instead of | in a flags check. - make buffer sink and src, audio and video work all together Clément Bœsch: * Switch to AVFrame: - aevalsrc - alphaextract - blend - cellauto - colormatrix - concat - earwax - ebur128 - edgedetect - geq - histeq - histogram - hue - kerndeint - life - movie - mp (with the help of Michael) - overlay - pad - pan - pp - pp - removelogo - sendcmd - showspectrum - showwaves - silencedetect - stereo3d - subtitles - super2xsai - swapuv - thumbnail - tile Hendrik Leppkes: * Switch to AVFrame: - aconvert - amerge - asetnsamples - atempo - biquads Matthieu Bouron: * Switch to AVFrame - alphamerge - decimate - volumedetect Stefano Sabatini: * Switch to AVFrame: - astreamsync - flite - framestep Signed-off-by: Michael Niedermayer <michaelni@gmx.at> Signed-off-by: Nicolas George <nicolas.george@normalesup.org> Signed-off-by: Clément Bœsch <ubitux@gmail.com> Signed-off-by: Hendrik Leppkes <h.leppkes@gmail.com> Signed-off-by: Matthieu Bouron <matthieu.bouron@gmail.com> Signed-off-by: Stefano Sabatini <stefasab@gmail.com> Merged-by: Michael Niedermayer <michaelni@gmx.at>
2013-03-10 03:30:30 +03:00
frame = av_frame_clone(test->picref);
} else
Merge commit '7e350379f87e7f74420b4813170fe808e2313911' * commit '7e350379f87e7f74420b4813170fe808e2313911': lavfi: switch to AVFrame. Conflicts: doc/filters.texi libavfilter/af_ashowinfo.c libavfilter/audio.c libavfilter/avfilter.c libavfilter/avfilter.h libavfilter/buffersink.c libavfilter/buffersrc.c libavfilter/buffersrc.h libavfilter/f_select.c libavfilter/f_setpts.c libavfilter/fifo.c libavfilter/split.c libavfilter/src_movie.c libavfilter/version.h libavfilter/vf_aspect.c libavfilter/vf_bbox.c libavfilter/vf_blackframe.c libavfilter/vf_delogo.c libavfilter/vf_drawbox.c libavfilter/vf_drawtext.c libavfilter/vf_fade.c libavfilter/vf_fieldorder.c libavfilter/vf_fps.c libavfilter/vf_frei0r.c libavfilter/vf_gradfun.c libavfilter/vf_hqdn3d.c libavfilter/vf_lut.c libavfilter/vf_overlay.c libavfilter/vf_pad.c libavfilter/vf_scale.c libavfilter/vf_showinfo.c libavfilter/vf_transpose.c libavfilter/vf_vflip.c libavfilter/vf_yadif.c libavfilter/video.c libavfilter/vsrc_testsrc.c libavfilter/yadif.h Following are notes about the merge authorship and various technical details. Michael Niedermayer: * Main merge operation, notably avfilter.c and video.c * Switch to AVFrame: - afade - anullsrc - apad - aresample - blackframe - deshake - idet - il - mandelbrot - mptestsrc - noise - setfield - smartblur - tinterlace * various merge changes and fixes in: - ashowinfo - blackdetect - field - fps - select - testsrc - yadif Nicolas George: * Switch to AVFrame: - make rawdec work with refcounted frames. Adapted from commit 759001c534287a96dc96d1e274665feb7059145d by Anton Khirnov. Also, fix the use of || instead of | in a flags check. - make buffer sink and src, audio and video work all together Clément Bœsch: * Switch to AVFrame: - aevalsrc - alphaextract - blend - cellauto - colormatrix - concat - earwax - ebur128 - edgedetect - geq - histeq - histogram - hue - kerndeint - life - movie - mp (with the help of Michael) - overlay - pad - pan - pp - pp - removelogo - sendcmd - showspectrum - showwaves - silencedetect - stereo3d - subtitles - super2xsai - swapuv - thumbnail - tile Hendrik Leppkes: * Switch to AVFrame: - aconvert - amerge - asetnsamples - atempo - biquads Matthieu Bouron: * Switch to AVFrame - alphamerge - decimate - volumedetect Stefano Sabatini: * Switch to AVFrame: - astreamsync - flite - framestep Signed-off-by: Michael Niedermayer <michaelni@gmx.at> Signed-off-by: Nicolas George <nicolas.george@normalesup.org> Signed-off-by: Clément Bœsch <ubitux@gmail.com> Signed-off-by: Hendrik Leppkes <h.leppkes@gmail.com> Signed-off-by: Matthieu Bouron <matthieu.bouron@gmail.com> Signed-off-by: Stefano Sabatini <stefasab@gmail.com> Merged-by: Michael Niedermayer <michaelni@gmx.at>
2013-03-10 03:30:30 +03:00
frame = ff_get_video_buffer(outlink, test->w, test->h);
if (!frame)
return AVERROR(ENOMEM);
Merge commit '7e350379f87e7f74420b4813170fe808e2313911' * commit '7e350379f87e7f74420b4813170fe808e2313911': lavfi: switch to AVFrame. Conflicts: doc/filters.texi libavfilter/af_ashowinfo.c libavfilter/audio.c libavfilter/avfilter.c libavfilter/avfilter.h libavfilter/buffersink.c libavfilter/buffersrc.c libavfilter/buffersrc.h libavfilter/f_select.c libavfilter/f_setpts.c libavfilter/fifo.c libavfilter/split.c libavfilter/src_movie.c libavfilter/version.h libavfilter/vf_aspect.c libavfilter/vf_bbox.c libavfilter/vf_blackframe.c libavfilter/vf_delogo.c libavfilter/vf_drawbox.c libavfilter/vf_drawtext.c libavfilter/vf_fade.c libavfilter/vf_fieldorder.c libavfilter/vf_fps.c libavfilter/vf_frei0r.c libavfilter/vf_gradfun.c libavfilter/vf_hqdn3d.c libavfilter/vf_lut.c libavfilter/vf_overlay.c libavfilter/vf_pad.c libavfilter/vf_scale.c libavfilter/vf_showinfo.c libavfilter/vf_transpose.c libavfilter/vf_vflip.c libavfilter/vf_yadif.c libavfilter/video.c libavfilter/vsrc_testsrc.c libavfilter/yadif.h Following are notes about the merge authorship and various technical details. Michael Niedermayer: * Main merge operation, notably avfilter.c and video.c * Switch to AVFrame: - afade - anullsrc - apad - aresample - blackframe - deshake - idet - il - mandelbrot - mptestsrc - noise - setfield - smartblur - tinterlace * various merge changes and fixes in: - ashowinfo - blackdetect - field - fps - select - testsrc - yadif Nicolas George: * Switch to AVFrame: - make rawdec work with refcounted frames. Adapted from commit 759001c534287a96dc96d1e274665feb7059145d by Anton Khirnov. Also, fix the use of || instead of | in a flags check. - make buffer sink and src, audio and video work all together Clément Bœsch: * Switch to AVFrame: - aevalsrc - alphaextract - blend - cellauto - colormatrix - concat - earwax - ebur128 - edgedetect - geq - histeq - histogram - hue - kerndeint - life - movie - mp (with the help of Michael) - overlay - pad - pan - pp - pp - removelogo - sendcmd - showspectrum - showwaves - silencedetect - stereo3d - subtitles - super2xsai - swapuv - thumbnail - tile Hendrik Leppkes: * Switch to AVFrame: - aconvert - amerge - asetnsamples - atempo - biquads Matthieu Bouron: * Switch to AVFrame - alphamerge - decimate - volumedetect Stefano Sabatini: * Switch to AVFrame: - astreamsync - flite - framestep Signed-off-by: Michael Niedermayer <michaelni@gmx.at> Signed-off-by: Nicolas George <nicolas.george@normalesup.org> Signed-off-by: Clément Bœsch <ubitux@gmail.com> Signed-off-by: Hendrik Leppkes <h.leppkes@gmail.com> Signed-off-by: Matthieu Bouron <matthieu.bouron@gmail.com> Signed-off-by: Stefano Sabatini <stefasab@gmail.com> Merged-by: Michael Niedermayer <michaelni@gmx.at>
2013-03-10 03:30:30 +03:00
frame->pts = test->pts;
frame->duration = 1;
#if FF_API_PKT_DURATION
FF_DISABLE_DEPRECATION_WARNINGS
frame->key_frame = 1;
FF_ENABLE_DEPRECATION_WARNINGS
#endif
frame->flags |= AV_FRAME_FLAG_KEY;
#if FF_API_INTERLACED_FRAME
FF_DISABLE_DEPRECATION_WARNINGS
frame->interlaced_frame = 0;
FF_ENABLE_DEPRECATION_WARNINGS
#endif
frame->flags &= ~AV_FRAME_FLAG_INTERLACED;
frame->pict_type = AV_PICTURE_TYPE_I;
frame->sample_aspect_ratio = test->sar;
if (!test->draw_once)
Merge commit '7e350379f87e7f74420b4813170fe808e2313911' * commit '7e350379f87e7f74420b4813170fe808e2313911': lavfi: switch to AVFrame. Conflicts: doc/filters.texi libavfilter/af_ashowinfo.c libavfilter/audio.c libavfilter/avfilter.c libavfilter/avfilter.h libavfilter/buffersink.c libavfilter/buffersrc.c libavfilter/buffersrc.h libavfilter/f_select.c libavfilter/f_setpts.c libavfilter/fifo.c libavfilter/split.c libavfilter/src_movie.c libavfilter/version.h libavfilter/vf_aspect.c libavfilter/vf_bbox.c libavfilter/vf_blackframe.c libavfilter/vf_delogo.c libavfilter/vf_drawbox.c libavfilter/vf_drawtext.c libavfilter/vf_fade.c libavfilter/vf_fieldorder.c libavfilter/vf_fps.c libavfilter/vf_frei0r.c libavfilter/vf_gradfun.c libavfilter/vf_hqdn3d.c libavfilter/vf_lut.c libavfilter/vf_overlay.c libavfilter/vf_pad.c libavfilter/vf_scale.c libavfilter/vf_showinfo.c libavfilter/vf_transpose.c libavfilter/vf_vflip.c libavfilter/vf_yadif.c libavfilter/video.c libavfilter/vsrc_testsrc.c libavfilter/yadif.h Following are notes about the merge authorship and various technical details. Michael Niedermayer: * Main merge operation, notably avfilter.c and video.c * Switch to AVFrame: - afade - anullsrc - apad - aresample - blackframe - deshake - idet - il - mandelbrot - mptestsrc - noise - setfield - smartblur - tinterlace * various merge changes and fixes in: - ashowinfo - blackdetect - field - fps - select - testsrc - yadif Nicolas George: * Switch to AVFrame: - make rawdec work with refcounted frames. Adapted from commit 759001c534287a96dc96d1e274665feb7059145d by Anton Khirnov. Also, fix the use of || instead of | in a flags check. - make buffer sink and src, audio and video work all together Clément Bœsch: * Switch to AVFrame: - aevalsrc - alphaextract - blend - cellauto - colormatrix - concat - earwax - ebur128 - edgedetect - geq - histeq - histogram - hue - kerndeint - life - movie - mp (with the help of Michael) - overlay - pad - pan - pp - pp - removelogo - sendcmd - showspectrum - showwaves - silencedetect - stereo3d - subtitles - super2xsai - swapuv - thumbnail - tile Hendrik Leppkes: * Switch to AVFrame: - aconvert - amerge - asetnsamples - atempo - biquads Matthieu Bouron: * Switch to AVFrame - alphamerge - decimate - volumedetect Stefano Sabatini: * Switch to AVFrame: - astreamsync - flite - framestep Signed-off-by: Michael Niedermayer <michaelni@gmx.at> Signed-off-by: Nicolas George <nicolas.george@normalesup.org> Signed-off-by: Clément Bœsch <ubitux@gmail.com> Signed-off-by: Hendrik Leppkes <h.leppkes@gmail.com> Signed-off-by: Matthieu Bouron <matthieu.bouron@gmail.com> Signed-off-by: Stefano Sabatini <stefasab@gmail.com> Merged-by: Michael Niedermayer <michaelni@gmx.at>
2013-03-10 03:30:30 +03:00
test->fill_picture_fn(outlink->src, frame);
test->pts++;
test->nb_frame++;
return ff_filter_frame(outlink, frame);
}
#if CONFIG_COLOR_FILTER
static const AVOption color_options[] = {
{ "color", "set color", OFFSET(color_rgba), AV_OPT_TYPE_COLOR, {.str = "black"}, 0, 0, FLAGSR },
{ "c", "set color", OFFSET(color_rgba), AV_OPT_TYPE_COLOR, {.str = "black"}, 0, 0, FLAGSR },
COMMON_OPTIONS
{ NULL }
};
AVFILTER_DEFINE_CLASS(color);
Merge commit '7e350379f87e7f74420b4813170fe808e2313911' * commit '7e350379f87e7f74420b4813170fe808e2313911': lavfi: switch to AVFrame. Conflicts: doc/filters.texi libavfilter/af_ashowinfo.c libavfilter/audio.c libavfilter/avfilter.c libavfilter/avfilter.h libavfilter/buffersink.c libavfilter/buffersrc.c libavfilter/buffersrc.h libavfilter/f_select.c libavfilter/f_setpts.c libavfilter/fifo.c libavfilter/split.c libavfilter/src_movie.c libavfilter/version.h libavfilter/vf_aspect.c libavfilter/vf_bbox.c libavfilter/vf_blackframe.c libavfilter/vf_delogo.c libavfilter/vf_drawbox.c libavfilter/vf_drawtext.c libavfilter/vf_fade.c libavfilter/vf_fieldorder.c libavfilter/vf_fps.c libavfilter/vf_frei0r.c libavfilter/vf_gradfun.c libavfilter/vf_hqdn3d.c libavfilter/vf_lut.c libavfilter/vf_overlay.c libavfilter/vf_pad.c libavfilter/vf_scale.c libavfilter/vf_showinfo.c libavfilter/vf_transpose.c libavfilter/vf_vflip.c libavfilter/vf_yadif.c libavfilter/video.c libavfilter/vsrc_testsrc.c libavfilter/yadif.h Following are notes about the merge authorship and various technical details. Michael Niedermayer: * Main merge operation, notably avfilter.c and video.c * Switch to AVFrame: - afade - anullsrc - apad - aresample - blackframe - deshake - idet - il - mandelbrot - mptestsrc - noise - setfield - smartblur - tinterlace * various merge changes and fixes in: - ashowinfo - blackdetect - field - fps - select - testsrc - yadif Nicolas George: * Switch to AVFrame: - make rawdec work with refcounted frames. Adapted from commit 759001c534287a96dc96d1e274665feb7059145d by Anton Khirnov. Also, fix the use of || instead of | in a flags check. - make buffer sink and src, audio and video work all together Clément Bœsch: * Switch to AVFrame: - aevalsrc - alphaextract - blend - cellauto - colormatrix - concat - earwax - ebur128 - edgedetect - geq - histeq - histogram - hue - kerndeint - life - movie - mp (with the help of Michael) - overlay - pad - pan - pp - pp - removelogo - sendcmd - showspectrum - showwaves - silencedetect - stereo3d - subtitles - super2xsai - swapuv - thumbnail - tile Hendrik Leppkes: * Switch to AVFrame: - aconvert - amerge - asetnsamples - atempo - biquads Matthieu Bouron: * Switch to AVFrame - alphamerge - decimate - volumedetect Stefano Sabatini: * Switch to AVFrame: - astreamsync - flite - framestep Signed-off-by: Michael Niedermayer <michaelni@gmx.at> Signed-off-by: Nicolas George <nicolas.george@normalesup.org> Signed-off-by: Clément Bœsch <ubitux@gmail.com> Signed-off-by: Hendrik Leppkes <h.leppkes@gmail.com> Signed-off-by: Matthieu Bouron <matthieu.bouron@gmail.com> Signed-off-by: Stefano Sabatini <stefasab@gmail.com> Merged-by: Michael Niedermayer <michaelni@gmx.at>
2013-03-10 03:30:30 +03:00
static void color_fill_picture(AVFilterContext *ctx, AVFrame *picref)
{
TestSourceContext *test = ctx->priv;
ff_fill_rectangle(&test->draw, &test->color,
picref->data, picref->linesize,
0, 0, test->w, test->h);
}
static av_cold int color_init(AVFilterContext *ctx)
{
TestSourceContext *test = ctx->priv;
test->fill_picture_fn = color_fill_picture;
test->draw_once = 1;
return init(ctx);
}
static int color_query_formats(AVFilterContext *ctx)
{
return ff_set_common_formats(ctx, ff_draw_supported_pixel_formats(0));
}
static int color_config_props(AVFilterLink *inlink)
{
AVFilterContext *ctx = inlink->src;
TestSourceContext *test = ctx->priv;
int ret;
ff_draw_init(&test->draw, inlink->format, 0);
ff_draw_color(&test->draw, &test->color, test->color_rgba);
test->w = ff_draw_round_to_sub(&test->draw, 0, -1, test->w);
test->h = ff_draw_round_to_sub(&test->draw, 1, -1, test->h);
if (av_image_check_size(test->w, test->h, 0, ctx) < 0)
return AVERROR(EINVAL);
if ((ret = config_props(inlink)) < 0)
return ret;
return 0;
}
static int color_process_command(AVFilterContext *ctx, const char *cmd, const char *args,
char *res, int res_len, int flags)
{
TestSourceContext *test = ctx->priv;
int ret;
ret = ff_filter_process_command(ctx, cmd, args, res, res_len, flags);
if (ret < 0)
return ret;
ff_draw_color(&test->draw, &test->color, test->color_rgba);
test->draw_once_reset = 1;
return 0;
}
static const AVFilterPad color_outputs[] = {
{
.name = "default",
.type = AVMEDIA_TYPE_VIDEO,
.config_props = color_config_props,
},
};
const AVFilter ff_vsrc_color = {
.name = "color",
.description = NULL_IF_CONFIG_SMALL("Provide an uniformly colored input."),
.priv_class = &color_class,
.priv_size = sizeof(TestSourceContext),
.init = color_init,
.uninit = uninit,
.activate = activate,
.inputs = NULL,
2021-08-12 13:05:31 +02:00
FILTER_OUTPUTS(color_outputs),
avfilter: Replace query_formats callback with union of list and callback If one looks at the many query_formats callbacks in existence, one will immediately recognize that there is one type of default callback for video and a slightly different default callback for audio: It is "return ff_set_common_formats_from_list(ctx, pix_fmts);" for video with a filter-specific pix_fmts list. For audio, it is the same with a filter-specific sample_fmts list together with ff_set_common_all_samplerates() and ff_set_common_all_channel_counts(). This commit allows to remove the boilerplate query_formats callbacks by replacing said callback with a union consisting the old callback and pointers for pixel and sample format arrays. For the not uncommon case in which these lists only contain a single entry (besides the sentinel) enum AVPixelFormat and enum AVSampleFormat fields are also added to the union to store them directly in the AVFilter, thereby avoiding a relocation. The state of said union will be contained in a new, dedicated AVFilter field (the nb_inputs and nb_outputs fields have been shrunk to uint8_t in order to create a hole for this new field; this is no problem, as the maximum of all the nb_inputs is four; for nb_outputs it is only two). The state's default value coincides with the earlier default of query_formats being unset, namely that the filter accepts all formats (and also sample rates and channel counts/layouts for audio) provided that these properties agree coincide for all inputs and outputs. By using different union members for audio and video filters the type-unsafety of using the same functions for audio and video lists will furthermore be more confined to formats.c than before. When the new fields are used, they will also avoid allocations: Currently something nearly equivalent to ff_default_query_formats() is called after every successful call to a query_formats callback; yet in the common case that the newly allocated AVFilterFormats are not used at all (namely if there are no free links) these newly allocated AVFilterFormats are freed again without ever being used. Filters no longer using the callback will not exhibit this any more. Reviewed-by: Paul B Mahol <onemda@gmail.com> Reviewed-by: Nicolas George <george@nsup.org> Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@outlook.com>
2021-09-27 12:07:35 +02:00
FILTER_QUERY_FUNC(color_query_formats),
.process_command = color_process_command,
};
#endif /* CONFIG_COLOR_FILTER */
2013-05-23 11:13:35 +03:00
#if CONFIG_HALDCLUTSRC_FILTER
static const AVOption haldclutsrc_options[] = {
{ "level", "set level", OFFSET(level), AV_OPT_TYPE_INT, {.i64 = 6}, 2, 16, FLAGS },
COMMON_OPTIONS_NOSIZE
2013-05-23 11:13:35 +03:00
{ NULL }
};
AVFILTER_DEFINE_CLASS(haldclutsrc);
static void haldclutsrc_fill_picture(AVFilterContext *ctx, AVFrame *frame)
{
int i, j, k, x = 0, y = 0, is16bit = 0, step;
uint32_t alpha = 0;
const TestSourceContext *hc = ctx->priv;
int level = hc->level;
float scale;
const int w = frame->width;
const int h = frame->height;
const uint8_t *data = frame->data[0];
const int linesize = frame->linesize[0];
const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(frame->format);
const int depth = desc->comp[0].depth;
const int planar = desc->flags & AV_PIX_FMT_FLAG_PLANAR;
const int planes = av_pix_fmt_count_planes(frame->format);
2013-05-23 11:13:35 +03:00
uint8_t rgba_map[4];
av_assert0(w == h && w == level*level*level);
ff_fill_rgba_map(rgba_map, frame->format);
alpha = (1 << depth) - 1;
is16bit = depth > 8;
2013-05-23 11:13:35 +03:00
step = av_get_padded_bits_per_pixel(desc) >> (3 + is16bit);
scale = ((float)alpha) / (level*level - 1);
2013-05-23 11:13:35 +03:00
#define LOAD_CLUT(nbits) do { \
uint##nbits##_t *dst = ((uint##nbits##_t *)(data + y*linesize)) + x*step; \
dst[rgba_map[0]] = av_clip_uint##nbits(i * scale); \
dst[rgba_map[1]] = av_clip_uint##nbits(j * scale); \
dst[rgba_map[2]] = av_clip_uint##nbits(k * scale); \
if (step == 4) \
dst[rgba_map[3]] = alpha; \
} while (0)
#define LOAD_CLUT_PLANAR(type, nbits) do { \
type *dst = ((type *)(frame->data[2] + y*frame->linesize[2])) + x; \
dst[0] = av_clip_uintp2(i * scale, nbits); \
dst = ((type *)(frame->data[0] + y*frame->linesize[0])) + x; \
dst[0] = av_clip_uintp2(j * scale, nbits); \
dst = ((type *)(frame->data[1] + y*frame->linesize[1])) + x; \
dst[0] = av_clip_uintp2(k * scale, nbits); \
if (planes == 4) { \
dst = ((type *)(frame->data[3] + y*linesize)) + x; \
dst[0] = alpha; \
} \
} while (0)
2013-05-23 11:13:35 +03:00
level *= level;
for (k = 0; k < level; k++) {
for (j = 0; j < level; j++) {
for (i = 0; i < level; i++) {
if (!planar) {
if (!is16bit)
LOAD_CLUT(8);
else
LOAD_CLUT(16);
} else {
switch (depth) {
case 8: LOAD_CLUT_PLANAR(uint8_t, 8); break;
case 9: LOAD_CLUT_PLANAR(uint16_t, 9); break;
case 10: LOAD_CLUT_PLANAR(uint16_t,10); break;
case 12: LOAD_CLUT_PLANAR(uint16_t,12); break;
case 14: LOAD_CLUT_PLANAR(uint16_t,14); break;
case 16: LOAD_CLUT_PLANAR(uint16_t,16); break;
}
}
2013-05-23 11:13:35 +03:00
if (++x == w) {
x = 0;
y++;
}
}
}
}
}
static av_cold int haldclutsrc_init(AVFilterContext *ctx)
{
TestSourceContext *hc = ctx->priv;
hc->fill_picture_fn = haldclutsrc_fill_picture;
hc->draw_once = 1;
return init(ctx);
}
static const enum AVPixelFormat haldclutsrc_pix_fmts[] = {
AV_PIX_FMT_RGB24, AV_PIX_FMT_BGR24,
AV_PIX_FMT_RGBA, AV_PIX_FMT_BGRA,
AV_PIX_FMT_ARGB, AV_PIX_FMT_ABGR,
AV_PIX_FMT_0RGB, AV_PIX_FMT_0BGR,
AV_PIX_FMT_RGB0, AV_PIX_FMT_BGR0,
AV_PIX_FMT_RGB48, AV_PIX_FMT_BGR48,
AV_PIX_FMT_RGBA64, AV_PIX_FMT_BGRA64,
AV_PIX_FMT_GBRP, AV_PIX_FMT_GBRAP,
AV_PIX_FMT_GBRP9,
AV_PIX_FMT_GBRP10, AV_PIX_FMT_GBRAP10,
AV_PIX_FMT_GBRP12, AV_PIX_FMT_GBRAP12,
AV_PIX_FMT_GBRP14,
AV_PIX_FMT_GBRP16, AV_PIX_FMT_GBRAP16,
AV_PIX_FMT_NONE,
};
2013-05-23 11:13:35 +03:00
static int haldclutsrc_config_props(AVFilterLink *outlink)
{
AVFilterContext *ctx = outlink->src;
TestSourceContext *hc = ctx->priv;
hc->w = hc->h = hc->level * hc->level * hc->level;
return config_props(outlink);
}
static const AVFilterPad haldclutsrc_outputs[] = {
{
.name = "default",
.type = AVMEDIA_TYPE_VIDEO,
.config_props = haldclutsrc_config_props,
},
};
const AVFilter ff_vsrc_haldclutsrc = {
.name = "haldclutsrc",
.description = NULL_IF_CONFIG_SMALL("Provide an identity Hald CLUT."),
.priv_class = &haldclutsrc_class,
.priv_size = sizeof(TestSourceContext),
.init = haldclutsrc_init,
.uninit = uninit,
.activate = activate,
.inputs = NULL,
2021-08-12 13:05:31 +02:00
FILTER_OUTPUTS(haldclutsrc_outputs),
FILTER_PIXFMTS_ARRAY(haldclutsrc_pix_fmts),
2013-05-23 11:13:35 +03:00
};
#endif /* CONFIG_HALDCLUTSRC_FILTER */
AVFILTER_DEFINE_CLASS_EXT(nullsrc_yuvtestsrc, "nullsrc/yuvtestsrc", options);
#if CONFIG_NULLSRC_FILTER
Merge commit '7e350379f87e7f74420b4813170fe808e2313911' * commit '7e350379f87e7f74420b4813170fe808e2313911': lavfi: switch to AVFrame. Conflicts: doc/filters.texi libavfilter/af_ashowinfo.c libavfilter/audio.c libavfilter/avfilter.c libavfilter/avfilter.h libavfilter/buffersink.c libavfilter/buffersrc.c libavfilter/buffersrc.h libavfilter/f_select.c libavfilter/f_setpts.c libavfilter/fifo.c libavfilter/split.c libavfilter/src_movie.c libavfilter/version.h libavfilter/vf_aspect.c libavfilter/vf_bbox.c libavfilter/vf_blackframe.c libavfilter/vf_delogo.c libavfilter/vf_drawbox.c libavfilter/vf_drawtext.c libavfilter/vf_fade.c libavfilter/vf_fieldorder.c libavfilter/vf_fps.c libavfilter/vf_frei0r.c libavfilter/vf_gradfun.c libavfilter/vf_hqdn3d.c libavfilter/vf_lut.c libavfilter/vf_overlay.c libavfilter/vf_pad.c libavfilter/vf_scale.c libavfilter/vf_showinfo.c libavfilter/vf_transpose.c libavfilter/vf_vflip.c libavfilter/vf_yadif.c libavfilter/video.c libavfilter/vsrc_testsrc.c libavfilter/yadif.h Following are notes about the merge authorship and various technical details. Michael Niedermayer: * Main merge operation, notably avfilter.c and video.c * Switch to AVFrame: - afade - anullsrc - apad - aresample - blackframe - deshake - idet - il - mandelbrot - mptestsrc - noise - setfield - smartblur - tinterlace * various merge changes and fixes in: - ashowinfo - blackdetect - field - fps - select - testsrc - yadif Nicolas George: * Switch to AVFrame: - make rawdec work with refcounted frames. Adapted from commit 759001c534287a96dc96d1e274665feb7059145d by Anton Khirnov. Also, fix the use of || instead of | in a flags check. - make buffer sink and src, audio and video work all together Clément Bœsch: * Switch to AVFrame: - aevalsrc - alphaextract - blend - cellauto - colormatrix - concat - earwax - ebur128 - edgedetect - geq - histeq - histogram - hue - kerndeint - life - movie - mp (with the help of Michael) - overlay - pad - pan - pp - pp - removelogo - sendcmd - showspectrum - showwaves - silencedetect - stereo3d - subtitles - super2xsai - swapuv - thumbnail - tile Hendrik Leppkes: * Switch to AVFrame: - aconvert - amerge - asetnsamples - atempo - biquads Matthieu Bouron: * Switch to AVFrame - alphamerge - decimate - volumedetect Stefano Sabatini: * Switch to AVFrame: - astreamsync - flite - framestep Signed-off-by: Michael Niedermayer <michaelni@gmx.at> Signed-off-by: Nicolas George <nicolas.george@normalesup.org> Signed-off-by: Clément Bœsch <ubitux@gmail.com> Signed-off-by: Hendrik Leppkes <h.leppkes@gmail.com> Signed-off-by: Matthieu Bouron <matthieu.bouron@gmail.com> Signed-off-by: Stefano Sabatini <stefasab@gmail.com> Merged-by: Michael Niedermayer <michaelni@gmx.at>
2013-03-10 03:30:30 +03:00
static void nullsrc_fill_picture(AVFilterContext *ctx, AVFrame *picref) { }
static av_cold int nullsrc_init(AVFilterContext *ctx)
{
TestSourceContext *test = ctx->priv;
test->fill_picture_fn = nullsrc_fill_picture;
return init(ctx);
}
static const AVFilterPad nullsrc_outputs[] = {
{
.name = "default",
.type = AVMEDIA_TYPE_VIDEO,
.config_props = config_props,
},
};
const AVFilter ff_vsrc_nullsrc = {
.name = "nullsrc",
.description = NULL_IF_CONFIG_SMALL("Null video source, return unprocessed video frames."),
.priv_class = &nullsrc_yuvtestsrc_class,
.init = nullsrc_init,
.uninit = uninit,
.activate = activate,
.priv_size = sizeof(TestSourceContext),
.inputs = NULL,
2021-08-12 13:05:31 +02:00
FILTER_OUTPUTS(nullsrc_outputs),
};
#endif /* CONFIG_NULLSRC_FILTER */
#if CONFIG_TESTSRC_FILTER
static const AVOption testsrc_options[] = {
COMMON_OPTIONS
{ "decimals", "set number of decimals to show", OFFSET(nb_decimals), AV_OPT_TYPE_INT, {.i64=0}, 0, 17, FLAGS },
{ "n", "set number of decimals to show", OFFSET(nb_decimals), AV_OPT_TYPE_INT, {.i64=0}, 0, 17, FLAGS },
{ NULL }
};
AVFILTER_DEFINE_CLASS(testsrc);
2011-06-18 04:11:16 +03:00
/**
* 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, int segment_width,
int x, int y, int w, int h)
2011-06-18 04:11:16 +03:00
{
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, int dst_linesize,
int segment_width)
2011-06-18 04:11:16 +03:00
{
#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
2014-04-11 12:54:15 +03:00
struct segments {
2011-06-18 04:11:16 +03:00
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, AVFrame *frame)
2011-06-18 04:11:16 +03:00
{
TestSourceContext *test = ctx->priv;
2011-06-18 04:11:16 +03:00
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 = frame->data[0];
int width = frame->width;
int height = frame->height;
2011-06-18 04:11:16 +03:00
/* 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 += frame->linesize[0];
2011-06-18 04:11:16 +03:00
}
/* draw sliding color line */
p0 = p = data + frame->linesize[0] * (height * 3/4);
2011-06-18 04:11:16 +03:00
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;
}
p = p0;
2011-06-18 04:11:16 +03:00
for (y = height / 8; y > 0; y--) {
Merge commit '7e350379f87e7f74420b4813170fe808e2313911' * commit '7e350379f87e7f74420b4813170fe808e2313911': lavfi: switch to AVFrame. Conflicts: doc/filters.texi libavfilter/af_ashowinfo.c libavfilter/audio.c libavfilter/avfilter.c libavfilter/avfilter.h libavfilter/buffersink.c libavfilter/buffersrc.c libavfilter/buffersrc.h libavfilter/f_select.c libavfilter/f_setpts.c libavfilter/fifo.c libavfilter/split.c libavfilter/src_movie.c libavfilter/version.h libavfilter/vf_aspect.c libavfilter/vf_bbox.c libavfilter/vf_blackframe.c libavfilter/vf_delogo.c libavfilter/vf_drawbox.c libavfilter/vf_drawtext.c libavfilter/vf_fade.c libavfilter/vf_fieldorder.c libavfilter/vf_fps.c libavfilter/vf_frei0r.c libavfilter/vf_gradfun.c libavfilter/vf_hqdn3d.c libavfilter/vf_lut.c libavfilter/vf_overlay.c libavfilter/vf_pad.c libavfilter/vf_scale.c libavfilter/vf_showinfo.c libavfilter/vf_transpose.c libavfilter/vf_vflip.c libavfilter/vf_yadif.c libavfilter/video.c libavfilter/vsrc_testsrc.c libavfilter/yadif.h Following are notes about the merge authorship and various technical details. Michael Niedermayer: * Main merge operation, notably avfilter.c and video.c * Switch to AVFrame: - afade - anullsrc - apad - aresample - blackframe - deshake - idet - il - mandelbrot - mptestsrc - noise - setfield - smartblur - tinterlace * various merge changes and fixes in: - ashowinfo - blackdetect - field - fps - select - testsrc - yadif Nicolas George: * Switch to AVFrame: - make rawdec work with refcounted frames. Adapted from commit 759001c534287a96dc96d1e274665feb7059145d by Anton Khirnov. Also, fix the use of || instead of | in a flags check. - make buffer sink and src, audio and video work all together Clément Bœsch: * Switch to AVFrame: - aevalsrc - alphaextract - blend - cellauto - colormatrix - concat - earwax - ebur128 - edgedetect - geq - histeq - histogram - hue - kerndeint - life - movie - mp (with the help of Michael) - overlay - pad - pan - pp - pp - removelogo - sendcmd - showspectrum - showwaves - silencedetect - stereo3d - subtitles - super2xsai - swapuv - thumbnail - tile Hendrik Leppkes: * Switch to AVFrame: - aconvert - amerge - asetnsamples - atempo - biquads Matthieu Bouron: * Switch to AVFrame - alphamerge - decimate - volumedetect Stefano Sabatini: * Switch to AVFrame: - astreamsync - flite - framestep Signed-off-by: Michael Niedermayer <michaelni@gmx.at> Signed-off-by: Nicolas George <nicolas.george@normalesup.org> Signed-off-by: Clément Bœsch <ubitux@gmail.com> Signed-off-by: Hendrik Leppkes <h.leppkes@gmail.com> Signed-off-by: Matthieu Bouron <matthieu.bouron@gmail.com> Signed-off-by: Stefano Sabatini <stefasab@gmail.com> Merged-by: Michael Niedermayer <michaelni@gmx.at>
2013-03-10 03:30:30 +03:00
memcpy(p+frame->linesize[0], p, 3 * width);
p += frame->linesize[0];
2011-06-18 04:11:16 +03:00
}
/* draw digits */
seg_size = width / 80;
if (seg_size >= 1 && height >= 13 * seg_size) {
int64_t p10decimals = 1;
double time = av_q2d(test->time_base) * test->nb_frame *
ff_exp10(test->nb_decimals);
if (time >= INT_MAX)
return;
2013-04-17 22:22:52 +03:00
for (x = 0; x < test->nb_decimals; x++)
p10decimals *= 10;
second = av_rescale_rnd(test->nb_frame * test->time_base.num, p10decimals, test->time_base.den, AV_ROUND_ZERO);
2011-06-18 04:11:16 +03:00
x = width - (width - seg_size * 64) / 2;
y = (height - seg_size * 13) / 2;
p = data + (x*3 + y * frame->linesize[0]);
2011-06-18 04:11:16 +03:00
for (i = 0; i < 8; i++) {
p -= 3 * 8 * seg_size;
draw_digit(second % 10, p, frame->linesize[0], seg_size);
2011-06-18 04:11:16 +03:00
second /= 10;
if (second == 0)
break;
}
}
}
static av_cold int test_init(AVFilterContext *ctx)
2011-06-18 04:11:16 +03:00
{
TestSourceContext *test = ctx->priv;
2011-06-18 04:11:16 +03:00
test->fill_picture_fn = test_fill_picture;
return init(ctx);
2011-06-18 04:11:16 +03:00
}
static const AVFilterPad avfilter_vsrc_testsrc_outputs[] = {
{
.name = "default",
.type = AVMEDIA_TYPE_VIDEO,
.config_props = config_props,
},
};
const AVFilter ff_vsrc_testsrc = {
.name = "testsrc",
.description = NULL_IF_CONFIG_SMALL("Generate test pattern."),
.priv_size = sizeof(TestSourceContext),
.priv_class = &testsrc_class,
.init = test_init,
.uninit = uninit,
.activate = activate,
.inputs = NULL,
2021-08-12 13:05:31 +02:00
FILTER_OUTPUTS(avfilter_vsrc_testsrc_outputs),
FILTER_SINGLE_PIXFMT(AV_PIX_FMT_RGB24),
2011-06-18 04:11:16 +03:00
};
#endif /* CONFIG_TESTSRC_FILTER */
#if CONFIG_TESTSRC2_FILTER
static const AVOption testsrc2_options[] = {
COMMON_OPTIONS
{ "alpha", "set global alpha (opacity)", OFFSET(alpha), AV_OPT_TYPE_INT, {.i64 = 255}, 0, 255, FLAGS },
{ NULL }
};
AVFILTER_DEFINE_CLASS(testsrc2);
static void set_color(TestSourceContext *s, FFDrawColor *color, uint32_t argb)
{
uint8_t rgba[4] = { (argb >> 16) & 0xFF,
(argb >> 8) & 0xFF,
(argb >> 0) & 0xFF,
(argb >> 24) & 0xFF, };
ff_draw_color(&s->draw, color, rgba);
}
static uint32_t color_gradient(unsigned index)
{
unsigned si = index & 0xFF, sd = 0xFF - si;
switch (index >> 8) {
case 0: return 0xFF0000 + (si << 8);
case 1: return 0x00FF00 + (sd << 16);
case 2: return 0x00FF00 + (si << 0);
case 3: return 0x0000FF + (sd << 8);
case 4: return 0x0000FF + (si << 16);
case 5: return 0xFF0000 + (sd << 0);
default: av_assert0(0); return 0;
}
}
static void draw_text(TestSourceContext *s, AVFrame *frame, FFDrawColor *color,
int x0, int y0, const uint8_t *text)
{
int x = x0;
for (; *text; text++) {
if (*text == '\n') {
x = x0;
y0 += 16;
continue;
}
ff_blend_mask(&s->draw, color, frame->data, frame->linesize,
frame->width, frame->height,
avpriv_vga16_font + *text * 16, 1, 8, 16, 0, 0, x, y0);
x += 8;
}
}
static void test2_fill_picture(AVFilterContext *ctx, AVFrame *frame)
{
TestSourceContext *s = ctx->priv;
FFDrawColor color;
unsigned alpha = (uint32_t)s->alpha << 24;
/* colored background */
{
unsigned i, x = 0, x2;
x = 0;
for (i = 1; i < 7; i++) {
x2 = av_rescale(i, s->w, 6);
x2 = ff_draw_round_to_sub(&s->draw, 0, 0, x2);
set_color(s, &color, ((i & 1) ? 0xFF0000 : 0) |
((i & 2) ? 0x00FF00 : 0) |
((i & 4) ? 0x0000FF : 0) |
alpha);
ff_fill_rectangle(&s->draw, &color, frame->data, frame->linesize,
x, 0, x2 - x, frame->height);
x = x2;
}
}
/* oblique gradient */
/* note: too slow if using blending */
if (s->h >= 64) {
unsigned x, dx, y0, y, g0, g;
dx = ff_draw_round_to_sub(&s->draw, 0, +1, 1);
y0 = av_rescale_q(s->pts, s->time_base, av_make_q(2, s->h - 16));
g0 = av_rescale_q(s->pts, s->time_base, av_make_q(1, 128));
for (x = 0; x < s->w; x += dx) {
g = (av_rescale(x, 6 * 256, s->w) + g0) % (6 * 256);
set_color(s, &color, color_gradient(g) | alpha);
y = y0 + av_rescale(x, s->h / 2, s->w);
y %= 2 * (s->h - 16);
if (y > s->h - 16)
y = 2 * (s->h - 16) - y;
y = ff_draw_round_to_sub(&s->draw, 1, 0, y);
ff_fill_rectangle(&s->draw, &color, frame->data, frame->linesize,
x, y, dx, 16);
}
}
/* top right: draw clock hands */
if (s->w >= 64 && s->h >= 64) {
int l = (FFMIN(s->w, s->h) - 32) >> 1;
int steps = FFMAX(4, l >> 5);
int xc = (s->w >> 2) + (s->w >> 1);
int yc = (s->h >> 2);
int cycle = l << 2;
int pos, xh, yh;
int c, i;
for (c = 0; c < 3; c++) {
set_color(s, &color, (0xBBBBBB ^ (0xFF << (c << 3))) | alpha);
pos = av_rescale_q(s->pts, s->time_base, av_make_q(64 >> (c << 1), cycle)) % cycle;
xh = pos < 1 * l ? pos :
pos < 2 * l ? l :
pos < 3 * l ? 3 * l - pos : 0;
yh = pos < 1 * l ? 0 :
pos < 2 * l ? pos - l :
pos < 3 * l ? l :
cycle - pos;
xh -= l >> 1;
yh -= l >> 1;
for (i = 1; i <= steps; i++) {
int x = av_rescale(xh, i, steps) + xc;
int y = av_rescale(yh, i, steps) + yc;
x = ff_draw_round_to_sub(&s->draw, 0, -1, x);
y = ff_draw_round_to_sub(&s->draw, 1, -1, y);
ff_fill_rectangle(&s->draw, &color, frame->data, frame->linesize,
x, y, 8, 8);
}
}
}
/* bottom left: beating rectangles */
if (s->w >= 64 && s->h >= 64) {
int l = (FFMIN(s->w, s->h) - 16) >> 2;
int cycle = l << 3;
int xc = (s->w >> 2);
int yc = (s->h >> 2) + (s->h >> 1);
int xm1 = ff_draw_round_to_sub(&s->draw, 0, -1, xc - 8);
int xm2 = ff_draw_round_to_sub(&s->draw, 0, +1, xc + 8);
int ym1 = ff_draw_round_to_sub(&s->draw, 1, -1, yc - 8);
int ym2 = ff_draw_round_to_sub(&s->draw, 1, +1, yc + 8);
int size, step, x1, x2, y1, y2;
size = av_rescale_q(s->pts, s->time_base, av_make_q(4, cycle));
step = size / l;
size %= l;
if (step & 1)
size = l - size;
step = (step >> 1) & 3;
set_color(s, &color, 0xFF808080);
x1 = ff_draw_round_to_sub(&s->draw, 0, -1, xc - 4 - size);
x2 = ff_draw_round_to_sub(&s->draw, 0, +1, xc + 4 + size);
y1 = ff_draw_round_to_sub(&s->draw, 1, -1, yc - 4 - size);
y2 = ff_draw_round_to_sub(&s->draw, 1, +1, yc + 4 + size);
if (step == 0 || step == 2)
ff_fill_rectangle(&s->draw, &color, frame->data, frame->linesize,
x1, ym1, x2 - x1, ym2 - ym1);
if (step == 1 || step == 2)
ff_fill_rectangle(&s->draw, &color, frame->data, frame->linesize,
xm1, y1, xm2 - xm1, y2 - y1);
if (step == 3)
ff_fill_rectangle(&s->draw, &color, frame->data, frame->linesize,
x1, y1, x2 - x1, y2 - y1);
}
/* bottom right: checker with random noise */
{
unsigned xmin = av_rescale(5, s->w, 8);
unsigned xmax = av_rescale(7, s->w, 8);
unsigned ymin = av_rescale(5, s->h, 8);
unsigned ymax = av_rescale(7, s->h, 8);
unsigned x, y, i, r;
uint8_t alpha[256];
r = s->pts;
for (y = ymin; y + 15 < ymax; y += 16) {
for (x = xmin; x + 15 < xmax; x += 16) {
if ((x ^ y) & 16)
continue;
for (i = 0; i < 256; i++) {
r = r * 1664525 + 1013904223;
alpha[i] = r >> 24;
}
set_color(s, &color, 0xFF00FF80);
ff_blend_mask(&s->draw, &color, frame->data, frame->linesize,
frame->width, frame->height,
alpha, 16, 16, 16, 3, 0, x, y);
}
}
}
/* bouncing square */
if (s->w >= 16 && s->h >= 16) {
unsigned w = s->w - 8;
unsigned h = s->h - 8;
unsigned x = av_rescale_q(s->pts, s->time_base, av_make_q(233, 55 * w)) % (w << 1);
unsigned y = av_rescale_q(s->pts, s->time_base, av_make_q(233, 89 * h)) % (h << 1);
if (x > w)
x = (w << 1) - x;
if (y > h)
y = (h << 1) - y;
x = ff_draw_round_to_sub(&s->draw, 0, -1, x);
y = ff_draw_round_to_sub(&s->draw, 1, -1, y);
set_color(s, &color, 0xFF8000FF);
ff_fill_rectangle(&s->draw, &color, frame->data, frame->linesize,
x, y, 8, 8);
}
/* top right: draw frame time and frame number */
{
char buf[256];
unsigned time;
time = av_rescale_q(s->pts, s->time_base, av_make_q(1, 1000)) % 86400000;
set_color(s, &color, 0xC0000000);
ff_blend_rectangle(&s->draw, &color, frame->data, frame->linesize,
frame->width, frame->height,
2, 2, 100, 36);
set_color(s, &color, 0xFFFF8000);
snprintf(buf, sizeof(buf), "%02d:%02d:%02d.%03d\n%12"PRIi64,
time / 3600000, (time / 60000) % 60, (time / 1000) % 60,
time % 1000, s->pts);
draw_text(s, frame, &color, 4, 4, buf);
}
}
static av_cold int test2_init(AVFilterContext *ctx)
{
TestSourceContext *s = ctx->priv;
s->fill_picture_fn = test2_fill_picture;
return init(ctx);
}
static int test2_query_formats(AVFilterContext *ctx)
{
return ff_set_common_formats(ctx, ff_draw_supported_pixel_formats(0));
}
static int test2_config_props(AVFilterLink *inlink)
{
AVFilterContext *ctx = inlink->src;
TestSourceContext *s = ctx->priv;
av_assert0(ff_draw_init(&s->draw, inlink->format, 0) >= 0);
s->w = ff_draw_round_to_sub(&s->draw, 0, -1, s->w);
s->h = ff_draw_round_to_sub(&s->draw, 1, -1, s->h);
if (av_image_check_size(s->w, s->h, 0, ctx) < 0)
return AVERROR(EINVAL);
return config_props(inlink);
}
static const AVFilterPad avfilter_vsrc_testsrc2_outputs[] = {
{
.name = "default",
.type = AVMEDIA_TYPE_VIDEO,
.config_props = test2_config_props,
},
};
const AVFilter ff_vsrc_testsrc2 = {
.name = "testsrc2",
.description = NULL_IF_CONFIG_SMALL("Generate another test pattern."),
.priv_size = sizeof(TestSourceContext),
.priv_class = &testsrc2_class,
.init = test2_init,
.uninit = uninit,
.activate = activate,
.inputs = NULL,
2021-08-12 13:05:31 +02:00
FILTER_OUTPUTS(avfilter_vsrc_testsrc2_outputs),
avfilter: Replace query_formats callback with union of list and callback If one looks at the many query_formats callbacks in existence, one will immediately recognize that there is one type of default callback for video and a slightly different default callback for audio: It is "return ff_set_common_formats_from_list(ctx, pix_fmts);" for video with a filter-specific pix_fmts list. For audio, it is the same with a filter-specific sample_fmts list together with ff_set_common_all_samplerates() and ff_set_common_all_channel_counts(). This commit allows to remove the boilerplate query_formats callbacks by replacing said callback with a union consisting the old callback and pointers for pixel and sample format arrays. For the not uncommon case in which these lists only contain a single entry (besides the sentinel) enum AVPixelFormat and enum AVSampleFormat fields are also added to the union to store them directly in the AVFilter, thereby avoiding a relocation. The state of said union will be contained in a new, dedicated AVFilter field (the nb_inputs and nb_outputs fields have been shrunk to uint8_t in order to create a hole for this new field; this is no problem, as the maximum of all the nb_inputs is four; for nb_outputs it is only two). The state's default value coincides with the earlier default of query_formats being unset, namely that the filter accepts all formats (and also sample rates and channel counts/layouts for audio) provided that these properties agree coincide for all inputs and outputs. By using different union members for audio and video filters the type-unsafety of using the same functions for audio and video lists will furthermore be more confined to formats.c than before. When the new fields are used, they will also avoid allocations: Currently something nearly equivalent to ff_default_query_formats() is called after every successful call to a query_formats callback; yet in the common case that the newly allocated AVFilterFormats are not used at all (namely if there are no free links) these newly allocated AVFilterFormats are freed again without ever being used. Filters no longer using the callback will not exhibit this any more. Reviewed-by: Paul B Mahol <onemda@gmail.com> Reviewed-by: Nicolas George <george@nsup.org> Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@outlook.com>
2021-09-27 12:07:35 +02:00
FILTER_QUERY_FUNC(test2_query_formats),
};
#endif /* CONFIG_TESTSRC2_FILTER */
#if CONFIG_RGBTESTSRC_FILTER
static const AVOption rgbtestsrc_options[] = {
COMMON_OPTIONS
{ "complement", "set complement colors", OFFSET(complement), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1, FLAGS },
{ "co", "set complement colors", OFFSET(complement), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1, FLAGS },
{ NULL }
};
AVFILTER_DEFINE_CLASS(rgbtestsrc);
#define R 0
#define G 1
#define B 2
#define A 3
static void rgbtest_put_pixel(uint8_t *dstp[4], int dst_linesizep[4],
int x, int y, unsigned r, unsigned g, unsigned b, enum AVPixelFormat fmt,
uint8_t rgba_map[4])
{
uint8_t *dst = dstp[0];
int dst_linesize = dst_linesizep[0];
uint32_t v;
uint8_t *p;
uint16_t *p16;
switch (fmt) {
case AV_PIX_FMT_BGR444: ((uint16_t*)(dst + y*dst_linesize))[x] = ((r >> 4) << 8) | ((g >> 4) << 4) | (b >> 4); break;
case AV_PIX_FMT_RGB444: ((uint16_t*)(dst + y*dst_linesize))[x] = ((b >> 4) << 8) | ((g >> 4) << 4) | (r >> 4); break;
case AV_PIX_FMT_BGR555: ((uint16_t*)(dst + y*dst_linesize))[x] = ((r>>3)<<10) | ((g>>3)<<5) | (b>>3); break;
case AV_PIX_FMT_RGB555: ((uint16_t*)(dst + y*dst_linesize))[x] = ((b>>3)<<10) | ((g>>3)<<5) | (r>>3); break;
case AV_PIX_FMT_BGR565: ((uint16_t*)(dst + y*dst_linesize))[x] = ((r>>3)<<11) | ((g>>2)<<5) | (b>>3); break;
case AV_PIX_FMT_RGB565: ((uint16_t*)(dst + y*dst_linesize))[x] = ((b>>3)<<11) | ((g>>2)<<5) | (r>>3); break;
case AV_PIX_FMT_RGB24:
case AV_PIX_FMT_BGR24:
v = (r << (rgba_map[R]*8)) + (g << (rgba_map[G]*8)) + (b << (rgba_map[B]*8));
p = dst + 3*x + y*dst_linesize;
AV_WL24(p, v);
break;
case AV_PIX_FMT_RGBA:
case AV_PIX_FMT_BGRA:
case AV_PIX_FMT_ARGB:
case AV_PIX_FMT_ABGR:
v = (r << (rgba_map[R]*8)) + (g << (rgba_map[G]*8)) + (b << (rgba_map[B]*8)) + (255U << (rgba_map[A]*8));
p = dst + 4*x + y*dst_linesize;
AV_WL32(p, v);
break;
case AV_PIX_FMT_GBRP:
p = dstp[0] + x + y * dst_linesizep[0];
p[0] = g;
p = dstp[1] + x + y * dst_linesizep[1];
p[0] = b;
p = dstp[2] + x + y * dst_linesizep[2];
p[0] = r;
break;
case AV_PIX_FMT_GBRP9:
case AV_PIX_FMT_GBRP10:
case AV_PIX_FMT_GBRP12:
case AV_PIX_FMT_GBRP14:
case AV_PIX_FMT_GBRP16:
p16 = (uint16_t *)(dstp[0] + x*2 + y * dst_linesizep[0]);
p16[0] = g;
p16 = (uint16_t *)(dstp[1] + x*2 + y * dst_linesizep[1]);
p16[0] = b;
p16 = (uint16_t *)(dstp[2] + x*2 + y * dst_linesizep[2]);
p16[0] = r;
break;
}
}
static void rgbtest_fill_picture_complement(AVFilterContext *ctx, AVFrame *frame)
{
TestSourceContext *test = ctx->priv;
int x, y, w = frame->width, h = frame->height;
for (y = 0; y < h; y++) {
for (x = 0; x < w; x++) {
int c = (1 << FFMAX(test->depth, 8))*x/w;
int r = 0, g = 0, b = 0;
if (6*y < h ) r = c;
else if (6*y < 2*h) g = c, b = c;
else if (6*y < 3*h) g = c;
else if (6*y < 4*h) r = c, b = c;
else if (6*y < 5*h) b = c;
else r = c, g = c;
rgbtest_put_pixel(frame->data, frame->linesize, x, y, r, g, b,
ctx->outputs[0]->format, test->rgba_map);
}
}
}
static void rgbtest_fill_picture(AVFilterContext *ctx, AVFrame *frame)
{
TestSourceContext *test = ctx->priv;
int x, y, w = frame->width, h = frame->height;
for (y = 0; y < h; y++) {
for (x = 0; x < w; x++) {
int c = (1 << FFMAX(test->depth, 8))*x/w;
int r = 0, g = 0, b = 0;
if (3*y < h ) r = c;
else if (3*y < 2*h) g = c;
else b = c;
rgbtest_put_pixel(frame->data, frame->linesize, x, y, r, g, b,
ctx->outputs[0]->format, test->rgba_map);
}
}
}
static av_cold int rgbtest_init(AVFilterContext *ctx)
{
TestSourceContext *test = ctx->priv;
test->draw_once = 1;
test->fill_picture_fn = test->complement ? rgbtest_fill_picture_complement : rgbtest_fill_picture;
return init(ctx);
}
static const enum AVPixelFormat rgbtest_pix_fmts[] = {
AV_PIX_FMT_RGBA, AV_PIX_FMT_ARGB, AV_PIX_FMT_BGRA, AV_PIX_FMT_ABGR,
AV_PIX_FMT_BGR24, AV_PIX_FMT_RGB24,
AV_PIX_FMT_RGB444, AV_PIX_FMT_BGR444,
AV_PIX_FMT_RGB565, AV_PIX_FMT_BGR565,
AV_PIX_FMT_RGB555, AV_PIX_FMT_BGR555,
AV_PIX_FMT_GBRP, AV_PIX_FMT_GBRP9, AV_PIX_FMT_GBRP10,
AV_PIX_FMT_GBRP12, AV_PIX_FMT_GBRP14, AV_PIX_FMT_GBRP16,
AV_PIX_FMT_NONE
};
static int rgbtest_config_props(AVFilterLink *outlink)
{
TestSourceContext *test = outlink->src->priv;
const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(outlink->format);
test->depth = desc->comp[0].depth;
ff_fill_rgba_map(test->rgba_map, outlink->format);
return config_props(outlink);
}
static const AVFilterPad avfilter_vsrc_rgbtestsrc_outputs[] = {
{
.name = "default",
.type = AVMEDIA_TYPE_VIDEO,
.config_props = rgbtest_config_props,
},
};
const AVFilter ff_vsrc_rgbtestsrc = {
.name = "rgbtestsrc",
.description = NULL_IF_CONFIG_SMALL("Generate RGB test pattern."),
.priv_size = sizeof(TestSourceContext),
.priv_class = &rgbtestsrc_class,
.init = rgbtest_init,
.uninit = uninit,
.activate = activate,
.inputs = NULL,
2021-08-12 13:05:31 +02:00
FILTER_OUTPUTS(avfilter_vsrc_rgbtestsrc_outputs),
FILTER_PIXFMTS_ARRAY(rgbtest_pix_fmts),
};
#endif /* CONFIG_RGBTESTSRC_FILTER */
2016-08-24 18:55:05 +02:00
#if CONFIG_YUVTESTSRC_FILTER
static void yuvtest_fill_picture8(AVFilterContext *ctx, AVFrame *frame)
{
int x, y, w = frame->width, h = frame->height / 3;
const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(frame->format);
const int factor = 1 << desc->comp[0].depth;
const int mid = 1 << (desc->comp[0].depth - 1);
uint8_t *ydst = frame->data[0];
uint8_t *udst = frame->data[1];
uint8_t *vdst = frame->data[2];
int ylinesize = frame->linesize[0];
int ulinesize = frame->linesize[1];
int vlinesize = frame->linesize[2];
for (y = 0; y < h; y++) {
for (x = 0; x < w; x++) {
int c = factor * x / w;
ydst[x] = c;
udst[x] = mid;
vdst[x] = mid;
}
ydst += ylinesize;
udst += ulinesize;
vdst += vlinesize;
}
h += h;
for (; y < h; y++) {
for (x = 0; x < w; x++) {
int c = factor * x / w;
ydst[x] = mid;
udst[x] = c;
vdst[x] = mid;
}
ydst += ylinesize;
udst += ulinesize;
vdst += vlinesize;
}
for (; y < frame->height; y++) {
for (x = 0; x < w; x++) {
int c = factor * x / w;
ydst[x] = mid;
udst[x] = mid;
vdst[x] = c;
}
ydst += ylinesize;
udst += ulinesize;
vdst += vlinesize;
}
}
static void yuvtest_fill_picture16(AVFilterContext *ctx, AVFrame *frame)
{
int x, y, w = frame->width, h = frame->height / 3;
const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(frame->format);
const int factor = 1 << desc->comp[0].depth;
const int mid = 1 << (desc->comp[0].depth - 1);
uint16_t *ydst = (uint16_t *)frame->data[0];
uint16_t *udst = (uint16_t *)frame->data[1];
uint16_t *vdst = (uint16_t *)frame->data[2];
int ylinesize = frame->linesize[0] / 2;
int ulinesize = frame->linesize[1] / 2;
int vlinesize = frame->linesize[2] / 2;
for (y = 0; y < h; y++) {
for (x = 0; x < w; x++) {
int c = factor * x / w;
ydst[x] = c;
udst[x] = mid;
vdst[x] = mid;
}
ydst += ylinesize;
udst += ulinesize;
vdst += vlinesize;
}
h += h;
for (; y < h; y++) {
for (x = 0; x < w; x++) {
int c = factor * x / w;
ydst[x] = mid;
udst[x] = c;
vdst[x] = mid;
}
ydst += ylinesize;
udst += ulinesize;
vdst += vlinesize;
}
for (; y < frame->height; y++) {
for (x = 0; x < w; x++) {
int c = factor * x / w;
ydst[x] = mid;
udst[x] = mid;
vdst[x] = c;
}
ydst += ylinesize;
udst += ulinesize;
vdst += vlinesize;
}
}
static av_cold int yuvtest_init(AVFilterContext *ctx)
{
TestSourceContext *test = ctx->priv;
test->draw_once = 1;
return init(ctx);
}
static const enum AVPixelFormat yuvtest_pix_fmts[] = {
AV_PIX_FMT_YUV444P, AV_PIX_FMT_YUVJ444P,
AV_PIX_FMT_YUV444P9, AV_PIX_FMT_YUV444P10,
AV_PIX_FMT_YUV444P12, AV_PIX_FMT_YUV444P14,
AV_PIX_FMT_YUV444P16,
AV_PIX_FMT_NONE
};
2016-08-24 18:55:05 +02:00
static int yuvtest_config_props(AVFilterLink *outlink)
{
TestSourceContext *test = outlink->src->priv;
const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(outlink->format);
test->fill_picture_fn = desc->comp[0].depth > 8 ? yuvtest_fill_picture16 : yuvtest_fill_picture8;
return config_props(outlink);
}
static const AVFilterPad avfilter_vsrc_yuvtestsrc_outputs[] = {
{
.name = "default",
.type = AVMEDIA_TYPE_VIDEO,
.config_props = yuvtest_config_props,
},
};
const AVFilter ff_vsrc_yuvtestsrc = {
2016-08-24 18:55:05 +02:00
.name = "yuvtestsrc",
.description = NULL_IF_CONFIG_SMALL("Generate YUV test pattern."),
.priv_size = sizeof(TestSourceContext),
.priv_class = &nullsrc_yuvtestsrc_class,
2016-08-24 18:55:05 +02:00
.init = yuvtest_init,
.uninit = uninit,
.activate = activate,
2016-08-24 18:55:05 +02:00
.inputs = NULL,
2021-08-12 13:05:31 +02:00
FILTER_OUTPUTS(avfilter_vsrc_yuvtestsrc_outputs),
FILTER_PIXFMTS_ARRAY(yuvtest_pix_fmts),
2016-08-24 18:55:05 +02:00
};
#endif /* CONFIG_YUVTESTSRC_FILTER */
#if CONFIG_PAL75BARS_FILTER || CONFIG_PAL100BARS_FILTER || CONFIG_SMPTEBARS_FILTER || CONFIG_SMPTEHDBARS_FILTER
static const uint8_t rainbow[7][4] = {
{ 180, 128, 128, 255 }, /* 75% white */
{ 162, 44, 142, 255 }, /* 75% yellow */
{ 131, 156, 44, 255 }, /* 75% cyan */
{ 112, 72, 58, 255 }, /* 75% green */
{ 84, 184, 198, 255 }, /* 75% magenta */
{ 65, 100, 212, 255 }, /* 75% red */
{ 35, 212, 114, 255 }, /* 75% blue */
};
static const uint8_t rainbow100[7][4] = {
{ 235, 128, 128, 255 }, /* 100% white */
{ 210, 16, 146, 255 }, /* 100% yellow */
{ 170, 166, 16, 255 }, /* 100% cyan */
{ 145, 54, 34, 255 }, /* 100% green */
{ 106, 202, 222, 255 }, /* 100% magenta */
{ 81, 90, 240, 255 }, /* 100% red */
{ 41, 240, 110, 255 }, /* 100% blue */
};
static const uint8_t rainbowhd[7][4] = {
{ 180, 128, 128, 255 }, /* 75% white */
{ 168, 44, 136, 255 }, /* 75% yellow */
{ 145, 147, 44, 255 }, /* 75% cyan */
{ 133, 63, 52, 255 }, /* 75% green */
{ 63, 193, 204, 255 }, /* 75% magenta */
{ 51, 109, 212, 255 }, /* 75% red */
{ 28, 212, 120, 255 }, /* 75% blue */
};
static const uint8_t wobnair[7][4] = {
{ 35, 212, 114, 255 }, /* 75% blue */
{ 19, 128, 128, 255 }, /* 7.5% intensity black */
{ 84, 184, 198, 255 }, /* 75% magenta */
{ 19, 128, 128, 255 }, /* 7.5% intensity black */
{ 131, 156, 44, 255 }, /* 75% cyan */
{ 19, 128, 128, 255 }, /* 7.5% intensity black */
{ 180, 128, 128, 255 }, /* 75% white */
};
static const uint8_t white[4] = { 235, 128, 128, 255 };
/* pluge pulses */
static const uint8_t neg4ire[4] = { 7, 128, 128, 255 };
static const uint8_t pos4ire[4] = { 24, 128, 128, 255 };
/* fudged Q/-I */
static const uint8_t i_pixel[4] = { 57, 156, 97, 255 };
static const uint8_t q_pixel[4] = { 44, 171, 147, 255 };
static const uint8_t gray40[4] = { 104, 128, 128, 255 };
static const uint8_t gray15[4] = { 49, 128, 128, 255 };
static const uint8_t cyan[4] = { 188, 154, 16, 255 };
static const uint8_t yellow[4] = { 219, 16, 138, 255 };
static const uint8_t blue[4] = { 32, 240, 118, 255 };
static const uint8_t red[4] = { 63, 102, 240, 255 };
static const uint8_t black0[4] = { 16, 128, 128, 255 };
static const uint8_t black2[4] = { 20, 128, 128, 255 };
static const uint8_t black4[4] = { 25, 128, 128, 255 };
static const uint8_t neg2[4] = { 12, 128, 128, 255 };
static void draw_bar(TestSourceContext *test, const uint8_t color[4],
int x, int y, int w, int h,
AVFrame *frame)
{
const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(frame->format);
uint8_t *p, *p0;
int plane;
x = FFMIN(x, test->w - 1);
y = FFMIN(y, test->h - 1);
w = FFMAX(FFMIN(w, test->w - x), 0);
h = FFMAX(FFMIN(h, test->h - y), 0);
av_assert0(x + w <= test->w);
av_assert0(y + h <= test->h);
for (plane = 0; frame->data[plane]; plane++) {
const int c = color[plane];
const int linesize = frame->linesize[plane];
int i, px, py, pw, ph;
if (plane == 1 || plane == 2) {
px = x >> desc->log2_chroma_w;
pw = AV_CEIL_RSHIFT(w, desc->log2_chroma_w);
py = y >> desc->log2_chroma_h;
ph = AV_CEIL_RSHIFT(h, desc->log2_chroma_h);
} else {
px = x;
pw = w;
py = y;
ph = h;
}
p0 = p = frame->data[plane] + py * linesize + px;
memset(p, c, pw);
p += linesize;
for (i = 1; i < ph; i++, p += linesize)
memcpy(p, p0, pw);
}
}
static const enum AVPixelFormat smptebars_pix_fmts[] = {
AV_PIX_FMT_YUV420P, AV_PIX_FMT_YUV422P,
AV_PIX_FMT_YUV440P, AV_PIX_FMT_YUV444P,
AV_PIX_FMT_YUV410P, AV_PIX_FMT_YUV411P,
AV_PIX_FMT_NONE,
};
static const AVFilterPad smptebars_outputs[] = {
{
.name = "default",
.type = AVMEDIA_TYPE_VIDEO,
.config_props = config_props,
},
};
AVFILTER_DEFINE_CLASS_EXT(palbars, "pal(75|100)bars", options);
#if CONFIG_PAL75BARS_FILTER
static void pal75bars_fill_picture(AVFilterContext *ctx, AVFrame *picref)
{
TestSourceContext *test = ctx->priv;
int r_w, i, x = 0;
const AVPixFmtDescriptor *pixdesc = av_pix_fmt_desc_get(picref->format);
picref->color_range = AVCOL_RANGE_MPEG;
picref->colorspace = AVCOL_SPC_BT470BG;
r_w = FFALIGN((test->w + 7) / 8, 1 << pixdesc->log2_chroma_w);
draw_bar(test, white, x, 0, r_w, test->h, picref);
x += r_w;
for (i = 1; i < 7; i++) {
draw_bar(test, rainbow[i], x, 0, r_w, test->h, picref);
x += r_w;
}
draw_bar(test, black0, x, 0, r_w, test->h, picref);
}
static av_cold int pal75bars_init(AVFilterContext *ctx)
{
TestSourceContext *test = ctx->priv;
test->fill_picture_fn = pal75bars_fill_picture;
test->draw_once = 1;
return init(ctx);
}
const AVFilter ff_vsrc_pal75bars = {
.name = "pal75bars",
.description = NULL_IF_CONFIG_SMALL("Generate PAL 75% color bars."),
.priv_class = &palbars_class,
.priv_size = sizeof(TestSourceContext),
.init = pal75bars_init,
.uninit = uninit,
.activate = activate,
.inputs = NULL,
2021-08-12 13:05:31 +02:00
FILTER_OUTPUTS(smptebars_outputs),
FILTER_PIXFMTS_ARRAY(smptebars_pix_fmts),
};
#endif /* CONFIG_PAL75BARS_FILTER */
#if CONFIG_PAL100BARS_FILTER
static void pal100bars_fill_picture(AVFilterContext *ctx, AVFrame *picref)
{
TestSourceContext *test = ctx->priv;
int r_w, i, x = 0;
const AVPixFmtDescriptor *pixdesc = av_pix_fmt_desc_get(picref->format);
picref->color_range = AVCOL_RANGE_MPEG;
picref->colorspace = AVCOL_SPC_BT470BG;
r_w = FFALIGN((test->w + 7) / 8, 1 << pixdesc->log2_chroma_w);
for (i = 0; i < 7; i++) {
draw_bar(test, rainbow100[i], x, 0, r_w, test->h, picref);
x += r_w;
}
draw_bar(test, black0, x, 0, r_w, test->h, picref);
}
static av_cold int pal100bars_init(AVFilterContext *ctx)
{
TestSourceContext *test = ctx->priv;
test->fill_picture_fn = pal100bars_fill_picture;
test->draw_once = 1;
return init(ctx);
}
const AVFilter ff_vsrc_pal100bars = {
.name = "pal100bars",
.description = NULL_IF_CONFIG_SMALL("Generate PAL 100% color bars."),
.priv_class = &palbars_class,
.priv_size = sizeof(TestSourceContext),
.init = pal100bars_init,
.uninit = uninit,
.activate = activate,
.inputs = NULL,
2021-08-12 13:05:31 +02:00
FILTER_OUTPUTS(smptebars_outputs),
FILTER_PIXFMTS_ARRAY(smptebars_pix_fmts),
};
#endif /* CONFIG_PAL100BARS_FILTER */
AVFILTER_DEFINE_CLASS_EXT(smptebars, "smpte(hd)bars", options);
#if CONFIG_SMPTEBARS_FILTER
Merge commit '7e350379f87e7f74420b4813170fe808e2313911' * commit '7e350379f87e7f74420b4813170fe808e2313911': lavfi: switch to AVFrame. Conflicts: doc/filters.texi libavfilter/af_ashowinfo.c libavfilter/audio.c libavfilter/avfilter.c libavfilter/avfilter.h libavfilter/buffersink.c libavfilter/buffersrc.c libavfilter/buffersrc.h libavfilter/f_select.c libavfilter/f_setpts.c libavfilter/fifo.c libavfilter/split.c libavfilter/src_movie.c libavfilter/version.h libavfilter/vf_aspect.c libavfilter/vf_bbox.c libavfilter/vf_blackframe.c libavfilter/vf_delogo.c libavfilter/vf_drawbox.c libavfilter/vf_drawtext.c libavfilter/vf_fade.c libavfilter/vf_fieldorder.c libavfilter/vf_fps.c libavfilter/vf_frei0r.c libavfilter/vf_gradfun.c libavfilter/vf_hqdn3d.c libavfilter/vf_lut.c libavfilter/vf_overlay.c libavfilter/vf_pad.c libavfilter/vf_scale.c libavfilter/vf_showinfo.c libavfilter/vf_transpose.c libavfilter/vf_vflip.c libavfilter/vf_yadif.c libavfilter/video.c libavfilter/vsrc_testsrc.c libavfilter/yadif.h Following are notes about the merge authorship and various technical details. Michael Niedermayer: * Main merge operation, notably avfilter.c and video.c * Switch to AVFrame: - afade - anullsrc - apad - aresample - blackframe - deshake - idet - il - mandelbrot - mptestsrc - noise - setfield - smartblur - tinterlace * various merge changes and fixes in: - ashowinfo - blackdetect - field - fps - select - testsrc - yadif Nicolas George: * Switch to AVFrame: - make rawdec work with refcounted frames. Adapted from commit 759001c534287a96dc96d1e274665feb7059145d by Anton Khirnov. Also, fix the use of || instead of | in a flags check. - make buffer sink and src, audio and video work all together Clément Bœsch: * Switch to AVFrame: - aevalsrc - alphaextract - blend - cellauto - colormatrix - concat - earwax - ebur128 - edgedetect - geq - histeq - histogram - hue - kerndeint - life - movie - mp (with the help of Michael) - overlay - pad - pan - pp - pp - removelogo - sendcmd - showspectrum - showwaves - silencedetect - stereo3d - subtitles - super2xsai - swapuv - thumbnail - tile Hendrik Leppkes: * Switch to AVFrame: - aconvert - amerge - asetnsamples - atempo - biquads Matthieu Bouron: * Switch to AVFrame - alphamerge - decimate - volumedetect Stefano Sabatini: * Switch to AVFrame: - astreamsync - flite - framestep Signed-off-by: Michael Niedermayer <michaelni@gmx.at> Signed-off-by: Nicolas George <nicolas.george@normalesup.org> Signed-off-by: Clément Bœsch <ubitux@gmail.com> Signed-off-by: Hendrik Leppkes <h.leppkes@gmail.com> Signed-off-by: Matthieu Bouron <matthieu.bouron@gmail.com> Signed-off-by: Stefano Sabatini <stefasab@gmail.com> Merged-by: Michael Niedermayer <michaelni@gmx.at>
2013-03-10 03:30:30 +03:00
static void smptebars_fill_picture(AVFilterContext *ctx, AVFrame *picref)
{
TestSourceContext *test = ctx->priv;
int r_w, r_h, w_h, p_w, p_h, i, tmp, x = 0;
const AVPixFmtDescriptor *pixdesc = av_pix_fmt_desc_get(picref->format);
picref->colorspace = AVCOL_SPC_BT470BG;
r_w = FFALIGN((test->w + 6) / 7, 1 << pixdesc->log2_chroma_w);
r_h = FFALIGN(test->h * 2 / 3, 1 << pixdesc->log2_chroma_h);
w_h = FFALIGN(test->h * 3 / 4 - r_h, 1 << pixdesc->log2_chroma_h);
p_w = FFALIGN(r_w * 5 / 4, 1 << pixdesc->log2_chroma_w);
p_h = test->h - w_h - r_h;
for (i = 0; i < 7; i++) {
draw_bar(test, rainbow[i], x, 0, r_w, r_h, picref);
draw_bar(test, wobnair[i], x, r_h, r_w, w_h, picref);
x += r_w;
}
x = 0;
draw_bar(test, i_pixel, x, r_h + w_h, p_w, p_h, picref);
x += p_w;
draw_bar(test, white, x, r_h + w_h, p_w, p_h, picref);
x += p_w;
draw_bar(test, q_pixel, x, r_h + w_h, p_w, p_h, picref);
x += p_w;
tmp = FFALIGN(5 * r_w - x, 1 << pixdesc->log2_chroma_w);
draw_bar(test, black0, x, r_h + w_h, tmp, p_h, picref);
x += tmp;
tmp = FFALIGN(r_w / 3, 1 << pixdesc->log2_chroma_w);
draw_bar(test, neg4ire, x, r_h + w_h, tmp, p_h, picref);
x += tmp;
draw_bar(test, black0, x, r_h + w_h, tmp, p_h, picref);
x += tmp;
draw_bar(test, pos4ire, x, r_h + w_h, tmp, p_h, picref);
x += tmp;
draw_bar(test, black0, x, r_h + w_h, test->w - x, p_h, picref);
}
static av_cold int smptebars_init(AVFilterContext *ctx)
{
TestSourceContext *test = ctx->priv;
test->fill_picture_fn = smptebars_fill_picture;
test->draw_once = 1;
return init(ctx);
}
const AVFilter ff_vsrc_smptebars = {
.name = "smptebars",
.description = NULL_IF_CONFIG_SMALL("Generate SMPTE color bars."),
.priv_size = sizeof(TestSourceContext),
.priv_class = &smptebars_class,
.init = smptebars_init,
.uninit = uninit,
.activate = activate,
.inputs = NULL,
2021-08-12 13:05:31 +02:00
FILTER_OUTPUTS(smptebars_outputs),
FILTER_PIXFMTS_ARRAY(smptebars_pix_fmts),
};
#endif /* CONFIG_SMPTEBARS_FILTER */
#if CONFIG_SMPTEHDBARS_FILTER
static void smptehdbars_fill_picture(AVFilterContext *ctx, AVFrame *picref)
{
TestSourceContext *test = ctx->priv;
int d_w, r_w, r_h, l_w, i, tmp, x = 0, y = 0;
const AVPixFmtDescriptor *pixdesc = av_pix_fmt_desc_get(picref->format);
picref->colorspace = AVCOL_SPC_BT709;
d_w = FFALIGN(test->w / 8, 1 << pixdesc->log2_chroma_w);
r_h = FFALIGN(test->h * 7 / 12, 1 << pixdesc->log2_chroma_h);
draw_bar(test, gray40, x, 0, d_w, r_h, picref);
x += d_w;
r_w = FFALIGN((((test->w + 3) / 4) * 3) / 7, 1 << pixdesc->log2_chroma_w);
for (i = 0; i < 7; i++) {
draw_bar(test, rainbowhd[i], x, 0, r_w, r_h, picref);
x += r_w;
}
draw_bar(test, gray40, x, 0, test->w - x, r_h, picref);
y = r_h;
r_h = FFALIGN(test->h / 12, 1 << pixdesc->log2_chroma_h);
draw_bar(test, cyan, 0, y, d_w, r_h, picref);
x = d_w;
draw_bar(test, i_pixel, x, y, r_w, r_h, picref);
x += r_w;
tmp = r_w * 6;
draw_bar(test, rainbowhd[0], x, y, tmp, r_h, picref);
x += tmp;
l_w = x;
draw_bar(test, blue, x, y, test->w - x, r_h, picref);
y += r_h;
draw_bar(test, yellow, 0, y, d_w, r_h, picref);
x = d_w;
draw_bar(test, q_pixel, x, y, r_w, r_h, picref);
x += r_w;
for (i = 0; i < tmp; i += 1 << pixdesc->log2_chroma_w) {
uint8_t yramp[4] = {0};
yramp[0] = i * 255 / tmp;
yramp[1] = 128;
yramp[2] = 128;
yramp[3] = 255;
draw_bar(test, yramp, x, y, 1 << pixdesc->log2_chroma_w, r_h, picref);
x += 1 << pixdesc->log2_chroma_w;
}
draw_bar(test, red, x, y, test->w - x, r_h, picref);
y += r_h;
draw_bar(test, gray15, 0, y, d_w, test->h - y, picref);
x = d_w;
tmp = FFALIGN(r_w * 3 / 2, 1 << pixdesc->log2_chroma_w);
draw_bar(test, black0, x, y, tmp, test->h - y, picref);
x += tmp;
tmp = FFALIGN(r_w * 2, 1 << pixdesc->log2_chroma_w);
draw_bar(test, white, x, y, tmp, test->h - y, picref);
x += tmp;
tmp = FFALIGN(r_w * 5 / 6, 1 << pixdesc->log2_chroma_w);
draw_bar(test, black0, x, y, tmp, test->h - y, picref);
x += tmp;
tmp = FFALIGN(r_w / 3, 1 << pixdesc->log2_chroma_w);
draw_bar(test, neg2, x, y, tmp, test->h - y, picref);
x += tmp;
draw_bar(test, black0, x, y, tmp, test->h - y, picref);
x += tmp;
draw_bar(test, black2, x, y, tmp, test->h - y, picref);
x += tmp;
draw_bar(test, black0, x, y, tmp, test->h - y, picref);
x += tmp;
draw_bar(test, black4, x, y, tmp, test->h - y, picref);
x += tmp;
r_w = l_w - x;
draw_bar(test, black0, x, y, r_w, test->h - y, picref);
x += r_w;
draw_bar(test, gray15, x, y, test->w - x, test->h - y, picref);
}
static av_cold int smptehdbars_init(AVFilterContext *ctx)
{
TestSourceContext *test = ctx->priv;
test->fill_picture_fn = smptehdbars_fill_picture;
test->draw_once = 1;
return init(ctx);
}
const AVFilter ff_vsrc_smptehdbars = {
.name = "smptehdbars",
.description = NULL_IF_CONFIG_SMALL("Generate SMPTE HD color bars."),
.priv_class = &smptebars_class,
.priv_size = sizeof(TestSourceContext),
.init = smptehdbars_init,
.uninit = uninit,
.activate = activate,
.inputs = NULL,
2021-08-12 13:05:31 +02:00
FILTER_OUTPUTS(smptebars_outputs),
FILTER_PIXFMTS_ARRAY(smptebars_pix_fmts),
};
#endif /* CONFIG_SMPTEHDBARS_FILTER */
#endif /* CONFIG_SMPTEBARS_FILTER || CONFIG_SMPTEHDBARS_FILTER */
AVFILTER_DEFINE_CLASS_EXT(allyuv_allrgb, "allyuv/allrgb",
&options[NOSIZE_OPTIONS_OFFSET]);
#if CONFIG_ALLYUV_FILTER
static void allyuv_fill_picture(AVFilterContext *ctx, AVFrame *frame)
{
const int ys = frame->linesize[0];
const int us = frame->linesize[1];
const int vs = frame->linesize[2];
int x, y, j;
for (y = 0; y < 4096; y++) {
for (x = 0; x < 2048; x++) {
frame->data[0][y * ys + x] = ((x / 8) % 256);
frame->data[0][y * ys + 4095 - x] = ((x / 8) % 256);
}
for (x = 0; x < 2048; x+=8) {
for (j = 0; j < 8; j++) {
frame->data[1][vs * y + x + j] = (y%16 + (j % 8) * 16);
frame->data[1][vs * y + 4095 - x - j] = (128 + y%16 + (j % 8) * 16);
}
}
for (x = 0; x < 4096; x++)
frame->data[2][y * us + x] = 256 * y / 4096;
}
}
static av_cold int allyuv_init(AVFilterContext *ctx)
{
TestSourceContext *test = ctx->priv;
test->w = test->h = 4096;
test->draw_once = 1;
test->fill_picture_fn = allyuv_fill_picture;
return init(ctx);
}
static const AVFilterPad avfilter_vsrc_allyuv_outputs[] = {
{
.name = "default",
.type = AVMEDIA_TYPE_VIDEO,
.config_props = config_props,
},
};
const AVFilter ff_vsrc_allyuv = {
.name = "allyuv",
.description = NULL_IF_CONFIG_SMALL("Generate all yuv colors."),
.priv_size = sizeof(TestSourceContext),
.priv_class = &allyuv_allrgb_class,
.init = allyuv_init,
.uninit = uninit,
.activate = activate,
.inputs = NULL,
2021-08-12 13:05:31 +02:00
FILTER_OUTPUTS(avfilter_vsrc_allyuv_outputs),
FILTER_PIXFMTS(AV_PIX_FMT_YUV444P, AV_PIX_FMT_GBRP),
};
#endif /* CONFIG_ALLYUV_FILTER */
#if CONFIG_ALLRGB_FILTER
static void allrgb_fill_picture(AVFilterContext *ctx, AVFrame *frame)
{
unsigned x, y;
const int linesize = frame->linesize[0];
uint8_t *line = frame->data[0];
for (y = 0; y < 4096; y++) {
uint8_t *dst = line;
for (x = 0; x < 4096; x++) {
*dst++ = x;
*dst++ = y;
*dst++ = (x >> 8) | ((y >> 8) << 4);
}
line += linesize;
}
}
static av_cold int allrgb_init(AVFilterContext *ctx)
{
TestSourceContext *test = ctx->priv;
test->w = test->h = 4096;
test->draw_once = 1;
test->fill_picture_fn = allrgb_fill_picture;
return init(ctx);
}
static int allrgb_config_props(AVFilterLink *outlink)
{
TestSourceContext *test = outlink->src->priv;
ff_fill_rgba_map(test->rgba_map, outlink->format);
return config_props(outlink);
}
static const AVFilterPad avfilter_vsrc_allrgb_outputs[] = {
{
.name = "default",
.type = AVMEDIA_TYPE_VIDEO,
.config_props = allrgb_config_props,
},
};
const AVFilter ff_vsrc_allrgb = {
.name = "allrgb",
.description = NULL_IF_CONFIG_SMALL("Generate all RGB colors."),
.priv_size = sizeof(TestSourceContext),
.priv_class = &allyuv_allrgb_class,
.init = allrgb_init,
.uninit = uninit,
.activate = activate,
.inputs = NULL,
2021-08-12 13:05:31 +02:00
FILTER_OUTPUTS(avfilter_vsrc_allrgb_outputs),
FILTER_SINGLE_PIXFMT(AV_PIX_FMT_RGB24),
};
#endif /* CONFIG_ALLRGB_FILTER */
#if CONFIG_COLORSPECTRUM_FILTER
static const AVOption colorspectrum_options[] = {
COMMON_OPTIONS
{ "type", "set the color spectrum type", OFFSET(type), AV_OPT_TYPE_INT, {.i64=0}, 0, 2, FLAGS, "type" },
{ "black","fade to black", 0, AV_OPT_TYPE_CONST,{.i64=0},0, 0, FLAGS, "type" },
{ "white","fade to white", 0, AV_OPT_TYPE_CONST,{.i64=1},0, 0, FLAGS, "type" },
{ "all", "white to black", 0, AV_OPT_TYPE_CONST,{.i64=2},0, 0, FLAGS, "type" },
{ NULL }
};
AVFILTER_DEFINE_CLASS(colorspectrum);
static inline float mix(float a, float b, float mix)
{
return a * mix + b * (1.f - mix);
}
static void hsb2rgb(const float *c, float *rgb)
{
rgb[0] = av_clipf(fabsf(fmodf(c[0] * 6.f + 0.f, 6.f) - 3.f) - 1.f, 0.f, 1.f);
rgb[1] = av_clipf(fabsf(fmodf(c[0] * 6.f + 4.f, 6.f) - 3.f) - 1.f, 0.f, 1.f);
rgb[2] = av_clipf(fabsf(fmodf(c[0] * 6.f + 2.f, 6.f) - 3.f) - 1.f, 0.f, 1.f);
rgb[0] = mix(c[3], (rgb[0] * rgb[0] * (3.f - 2.f * rgb[0])), c[1]) * c[2];
rgb[1] = mix(c[3], (rgb[1] * rgb[1] * (3.f - 2.f * rgb[1])), c[1]) * c[2];
rgb[2] = mix(c[3], (rgb[2] * rgb[2] * (3.f - 2.f * rgb[2])), c[1]) * c[2];
}
static void colorspectrum_fill_picture(AVFilterContext *ctx, AVFrame *frame)
{
TestSourceContext *test = ctx->priv;
const float w = frame->width - 1.f;
const float h = frame->height - 1.f;
float c[4];
for (int y = 0; y < frame->height; y++) {
float *r = (float *)(frame->data[2] + y * frame->linesize[2]);
float *g = (float *)(frame->data[0] + y * frame->linesize[0]);
float *b = (float *)(frame->data[1] + y * frame->linesize[1]);
const float yh = y / h;
c[1] = test->type == 2 ? yh > 0.5f ? 2.f * (yh - 0.5f) : 1.f - 2.f * yh : test->type == 1 ? 1.f - yh : yh;
c[2] = 1.f;
c[3] = test->type == 1 ? 1.f : test->type == 2 ? (yh > 0.5f ? 0.f : 1.f): 0.f;
for (int x = 0; x < frame->width; x++) {
float rgb[3];
c[0] = x / w;
hsb2rgb(c, rgb);
r[x] = rgb[0];
g[x] = rgb[1];
b[x] = rgb[2];
}
}
}
static av_cold int colorspectrum_init(AVFilterContext *ctx)
{
TestSourceContext *test = ctx->priv;
test->draw_once = 1;
test->fill_picture_fn = colorspectrum_fill_picture;
return init(ctx);
}
static const AVFilterPad avfilter_vsrc_colorspectrum_outputs[] = {
{
.name = "default",
.type = AVMEDIA_TYPE_VIDEO,
.config_props = config_props,
},
};
const AVFilter ff_vsrc_colorspectrum = {
.name = "colorspectrum",
.description = NULL_IF_CONFIG_SMALL("Generate colors spectrum."),
.priv_size = sizeof(TestSourceContext),
.priv_class = &colorspectrum_class,
.init = colorspectrum_init,
.uninit = uninit,
.activate = activate,
.inputs = NULL,
FILTER_OUTPUTS(avfilter_vsrc_colorspectrum_outputs),
FILTER_SINGLE_PIXFMT(AV_PIX_FMT_GBRPF32),
};
#endif /* CONFIG_COLORSPECTRUM_FILTER */
2022-04-10 19:12:53 +02:00
#if CONFIG_COLORCHART_FILTER
static const AVOption colorchart_options[] = {
COMMON_OPTIONS_NOSIZE
{ "patch_size", "set the single patch size", OFFSET(pw), AV_OPT_TYPE_IMAGE_SIZE, {.str="64x64"}, 0, 0, FLAGS },
{ "preset", "set the color checker chart preset", OFFSET(type), AV_OPT_TYPE_INT, {.i64=0}, 0, 1, FLAGS, "preset" },
{ "reference", "reference", 0, AV_OPT_TYPE_CONST,{.i64=0}, 0, 0, FLAGS, "preset" },
{ "skintones", "skintones", 0, AV_OPT_TYPE_CONST,{.i64=1}, 0, 0, FLAGS, "preset" },
{ NULL }
};
AVFILTER_DEFINE_CLASS(colorchart);
static const uint8_t reference_colors[][3] = {
{ 115, 82, 68 }, // dark skin
{ 194, 150, 130 }, // light skin
{ 98, 122, 157 }, // blue sky
{ 87, 108, 67 }, // foliage
{ 133, 128, 177 }, // blue flower
{ 103, 189, 170 }, // bluish green
{ 214, 126, 44 }, // orange
{ 80, 91, 166 }, // purple red
{ 193, 90, 99 }, // moderate red
{ 94, 60, 108 }, // purple
{ 157, 188, 64 }, // yellow green
{ 224, 163, 46 }, // orange yellow
{ 56, 61, 150 }, // blue
{ 70, 148, 73 }, // green
{ 175, 54, 60 }, // red
{ 231, 199, 31 }, // yellow
2022-04-10 19:12:53 +02:00
{ 187, 86, 149 }, // magenta
{ 8, 133, 161 }, // cyan
{ 243, 243, 242 }, // white
{ 200, 200, 200 }, // neutral 8
{ 160, 160, 160 }, // neutral 65
{ 122, 122, 121 }, // neutral 5
{ 85, 85, 85 }, // neutral 35
{ 52, 52, 52 }, // black
};
static const uint8_t skintones_colors[][3] = {
{ 54, 38, 43 },
{ 105, 43, 42 },
{ 147, 43, 43 },
{ 77, 41, 42 },
{ 134, 43, 41 },
{ 201, 134, 118 },
{ 59, 41, 41 },
{ 192, 103, 76 },
{ 208, 156, 141 },
{ 152, 82, 61 },
{ 162, 132, 118 },
{ 212, 171, 150 },
{ 205, 91, 31 },
{ 164, 100, 55 },
{ 204, 136, 95 },
{ 178, 142, 116 },
{ 210, 152, 108 },
{ 217, 167, 131 },
{ 206, 166, 126 },
{ 208, 163, 97 },
{ 245, 180, 0 },
{ 212, 184, 125 },
{ 179, 165, 150 },
{ 196, 184, 105 },
};
typedef struct ColorChartPreset {
int w, h;
const uint8_t (*colors)[3];
} ColorChartPreset;
static const ColorChartPreset colorchart_presets[] = {
{ 6, 4, reference_colors, },
{ 6, 4, skintones_colors, },
};
static int colorchart_config_props(AVFilterLink *inlink)
{
AVFilterContext *ctx = inlink->src;
TestSourceContext *s = ctx->priv;
av_assert0(ff_draw_init(&s->draw, inlink->format, 0) >= 0);
if (av_image_check_size(s->w, s->h, 0, ctx) < 0)
return AVERROR(EINVAL);
return config_props(inlink);
}
static void colorchart_fill_picture(AVFilterContext *ctx, AVFrame *frame)
{
TestSourceContext *test = ctx->priv;
const int preset = test->type;
const int w = colorchart_presets[preset].w;
const int h = colorchart_presets[preset].h;
const int pw = test->pw;
const int ph = test->pw;
for (int y = 0; y < h; y++) {
for (int x = 0; x < w; x++) {
uint32_t pc = AV_RB24(colorchart_presets[preset].colors[y * w + x]);
FFDrawColor color;
set_color(test, &color, pc);
ff_fill_rectangle(&test->draw, &color, frame->data, frame->linesize,
x * pw, y * ph, pw, ph);
}
}
}
static av_cold int colorchart_init(AVFilterContext *ctx)
{
TestSourceContext *test = ctx->priv;
const int preset = test->type;
const int w = colorchart_presets[preset].w;
const int h = colorchart_presets[preset].h;
test->w = w * test->pw;
test->h = h * test->ph;
test->draw_once = 1;
test->fill_picture_fn = colorchart_fill_picture;
return init(ctx);
}
static const AVFilterPad avfilter_vsrc_colorchart_outputs[] = {
{
.name = "default",
.type = AVMEDIA_TYPE_VIDEO,
.config_props = colorchart_config_props,
},
};
const AVFilter ff_vsrc_colorchart = {
.name = "colorchart",
.description = NULL_IF_CONFIG_SMALL("Generate color checker chart."),
.priv_size = sizeof(TestSourceContext),
.priv_class = &colorchart_class,
.init = colorchart_init,
.uninit = uninit,
.activate = activate,
.inputs = NULL,
FILTER_OUTPUTS(avfilter_vsrc_colorchart_outputs),
FILTER_SINGLE_PIXFMT(AV_PIX_FMT_GBRP),
};
#endif /* CONFIG_COLORCHART_FILTER */
#if CONFIG_ZONEPLATE_FILTER
static const AVOption zoneplate_options[] = {
COMMON_OPTIONS
{ "precision", "set LUT precision", OFFSET(lut_precision), AV_OPT_TYPE_INT, {.i64=10}, 4, 16, FLAGS },
{ "xo", "set X-axis offset", OFFSET(xo), AV_OPT_TYPE_INT, {.i64=0}, INT_MIN, INT_MAX, FLAGSR },
{ "yo", "set Y-axis offset", OFFSET(yo), AV_OPT_TYPE_INT, {.i64=0}, INT_MIN, INT_MAX, FLAGSR },
{ "to", "set T-axis offset", OFFSET(to), AV_OPT_TYPE_INT, {.i64=0}, INT_MIN, INT_MAX, FLAGSR },
{ "k0", "set 0-order phase", OFFSET(k0), AV_OPT_TYPE_INT, {.i64=0}, INT_MIN, INT_MAX, FLAGSR },
{ "kx", "set 1-order X-axis phase", OFFSET(kx), AV_OPT_TYPE_INT, {.i64=0}, INT_MIN, INT_MAX, FLAGSR },
{ "ky", "set 1-order Y-axis phase", OFFSET(ky), AV_OPT_TYPE_INT, {.i64=0}, INT_MIN, INT_MAX, FLAGSR },
{ "kt", "set 1-order T-axis phase", OFFSET(kt), AV_OPT_TYPE_INT, {.i64=0}, INT_MIN, INT_MAX, FLAGSR },
{ "kxt", "set X-axis*T-axis product phase", OFFSET(kxt), AV_OPT_TYPE_INT, {.i64=0}, INT_MIN, INT_MAX, FLAGSR },
{ "kyt", "set Y-axis*T-axis product phase", OFFSET(kyt), AV_OPT_TYPE_INT, {.i64=0}, INT_MIN, INT_MAX, FLAGSR },
{ "kxy", "set X-axis*Y-axis product phase", OFFSET(kxy), AV_OPT_TYPE_INT, {.i64=0}, INT_MIN, INT_MAX, FLAGSR },
{ "kx2", "set 2-order X-axis phase", OFFSET(kx2), AV_OPT_TYPE_INT, {.i64=0}, INT_MIN, INT_MAX, FLAGSR },
{ "ky2", "set 2-order Y-axis phase", OFFSET(ky2), AV_OPT_TYPE_INT, {.i64=0}, INT_MIN, INT_MAX, FLAGSR },
{ "kt2", "set 2-order T-axis phase", OFFSET(kt2), AV_OPT_TYPE_INT, {.i64=0}, INT_MIN, INT_MAX, FLAGSR },
{ "ku", "set 0-order U-color phase", OFFSET(kU), AV_OPT_TYPE_INT, {.i64=0}, INT_MIN, INT_MAX, FLAGSR },
{ "kv", "set 0-order V-color phase", OFFSET(kV), AV_OPT_TYPE_INT, {.i64=0}, INT_MIN, INT_MAX, FLAGSR },
{ NULL }
};
AVFILTER_DEFINE_CLASS(zoneplate);
#define ZONEPLATE_SLICE(name, type) \
static int zoneplate_fill_slice_##name(AVFilterContext *ctx, \
void *arg, int job, \
int nb_jobs) \
{ \
TestSourceContext *test = ctx->priv; \
AVFrame *frame = arg; \
const int w = frame->width; \
const int h = frame->height; \
const int kxt = test->kxt, kyt = test->kyt, kx2 = test->kx2; \
const int t = test->pts + test->to, k0 = test->k0; \
const int kt = test->kt, kt2 = test->kt2, ky2 = test->ky2; \
const int ky = test->ky, kx = test->kx, kxy = test->kxy; \
const int lut_mask = (1 << test->lut_precision) - 1; \
const int nkt2t = kt2 * t * t, nktt = kt * t; \
const int start = (h * job ) / nb_jobs; \
const int end = (h * (job+1)) / nb_jobs; \
const int ylinesize = frame->linesize[0] / sizeof(type); \
const int ulinesize = frame->linesize[1] / sizeof(type); \
const int vlinesize = frame->linesize[2] / sizeof(type); \
const int xreset = -(w / 2) - test->xo; \
const int yreset = -(h / 2) - test->yo + start; \
const int kU = test->kU, kV = test->kV; \
const int skxy = 0xffff / (w / 2); \
const int skx2 = 0xffff / w; \
const int dkxt = kxt * t; \
type *ydst = ((type *)frame->data[0]) + start * ylinesize; \
type *udst = ((type *)frame->data[1]) + start * ulinesize; \
type *vdst = ((type *)frame->data[2]) + start * vlinesize; \
const type *lut = (const type *)test->lut; \
int akx, akxt, aky, akyt; \
\
aky = start * ky; \
akyt = start * kyt * t; \
\
for (int j = start, y = yreset; j < end; j++, y++) { \
const int dkxy = kxy * y * skxy; \
const int nky2kt2 = (ky2 * y * y) / h + (nkt2t >> 1); \
int akxy = dkxy * xreset; \
\
akx = 0; \
akxt = 0; \
aky += ky; \
akyt += kyt * t; \
\
for (int i = 0, x = xreset; i < w; i++, x++) { \
int phase = k0, uphase = kU, vphase = kV; \
\
akx += kx; \
phase += akx + aky + nktt; \
\
akxt += dkxt; \
akxy += dkxy; \
phase += akxt + akyt; \
phase += akxy >> 16; \
phase += ((kx2 * x * x * skx2) >> 16) + nky2kt2; \
uphase += phase; \
vphase += phase; \
\
ydst[i] = lut[phase & lut_mask]; \
udst[i] = lut[uphase & lut_mask]; \
vdst[i] = lut[vphase & lut_mask]; \
} \
\
ydst += ylinesize; \
udst += ulinesize; \
vdst += vlinesize; \
} \
\
return 0; \
}
ZONEPLATE_SLICE( 8, uint8_t)
ZONEPLATE_SLICE( 9, uint16_t)
ZONEPLATE_SLICE(10, uint16_t)
ZONEPLATE_SLICE(12, uint16_t)
ZONEPLATE_SLICE(14, uint16_t)
ZONEPLATE_SLICE(16, uint16_t)
static void zoneplate_fill_picture(AVFilterContext *ctx, AVFrame *frame)
{
TestSourceContext *test = ctx->priv;
frame->color_range = AVCOL_RANGE_JPEG;
ff_filter_execute(ctx, test->fill_slice_fn, frame, NULL,
FFMIN(frame->height, ff_filter_get_nb_threads(ctx)));
}
static int zoneplate_config_props(AVFilterLink *outlink)
{
AVFilterContext *ctx = outlink->src;
TestSourceContext *test = ctx->priv;
const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(outlink->format);
const int lut_size = 1 << test->lut_precision;
const int depth = desc->comp[0].depth;
uint16_t *lut16;
uint8_t *lut8;
if (av_image_check_size(test->w, test->h, 0, ctx) < 0)
return AVERROR(EINVAL);
test->lut = av_calloc(lut_size, sizeof(*test->lut) * ((depth + 7) / 8));
if (!test->lut)
return AVERROR(ENOMEM);
lut8 = test->lut;
lut16 = (uint16_t *)test->lut;
switch (depth) {
case 8:
for (int i = 0; i < lut_size; i++)
lut8[i] = lrintf(255.f * (0.5f + 0.5f * sinf((2.f * M_PI * i) / lut_size)));
break;
default:
for (int i = 0; i < lut_size; i++)
lut16[i] = lrintf(((1 << depth) - 1) * (0.5f + 0.5f * sinf((2.f * M_PI * i) / lut_size)));
break;
}
test->draw_once = 0;
test->fill_picture_fn = zoneplate_fill_picture;
switch (depth) {
case 8: test->fill_slice_fn = zoneplate_fill_slice_8; break;
case 9: test->fill_slice_fn = zoneplate_fill_slice_9; break;
case 10: test->fill_slice_fn = zoneplate_fill_slice_10; break;
case 12: test->fill_slice_fn = zoneplate_fill_slice_12; break;
case 14: test->fill_slice_fn = zoneplate_fill_slice_14; break;
case 16: test->fill_slice_fn = zoneplate_fill_slice_16; break;
}
return config_props(outlink);
}
static const enum AVPixelFormat zoneplate_pix_fmts[] = {
AV_PIX_FMT_YUV444P, AV_PIX_FMT_YUV444P9,
AV_PIX_FMT_YUV444P10, AV_PIX_FMT_YUV444P12,
AV_PIX_FMT_YUV444P14, AV_PIX_FMT_YUV444P16,
AV_PIX_FMT_NONE,
};
static const AVFilterPad avfilter_vsrc_zoneplate_outputs[] = {
{
.name = "default",
.type = AVMEDIA_TYPE_VIDEO,
.config_props = zoneplate_config_props,
},
};
const AVFilter ff_vsrc_zoneplate = {
.name = "zoneplate",
.description = NULL_IF_CONFIG_SMALL("Generate zone-plate."),
.priv_size = sizeof(TestSourceContext),
.priv_class = &zoneplate_class,
.init = init,
.uninit = uninit,
.activate = activate,
.inputs = NULL,
FILTER_OUTPUTS(avfilter_vsrc_zoneplate_outputs),
FILTER_PIXFMTS_ARRAY(zoneplate_pix_fmts),
.flags = AVFILTER_FLAG_SLICE_THREADS,
.process_command = ff_filter_process_command,
};
#endif /* CONFIG_ZONEPLATE_FILTER */