FFmpeg
Loading...
Searching...
No Matches
avf_abitscope.c
Go to the documentation of this file.
1/*
2 * Copyright (c) 2016 Paul B Mahol
3 *
4 * This file is part of FFmpeg.
5 *
6 * FFmpeg is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * FFmpeg is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with FFmpeg; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19 */
20
21#include "libavutil/avstring.h"
23#include "libavutil/mem.h"
24#include "libavutil/opt.h"
26#include "avfilter.h"
27#include "filters.h"
28#include "formats.h"
29#include "audio.h"
30#include "video.h"
31
32typedef struct AudioBitScopeContext {
33 const AVClass *class;
34 int w, h;
36 char *colors;
37 int mode;
38
41 int depth;
43 uint8_t *fg;
44
45 uint64_t counter[64];
46
49
50#define OFFSET(x) offsetof(AudioBitScopeContext, x)
51#define FLAGS AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_VIDEO_PARAM
52
53static const AVOption abitscope_options[] = {
54 { "rate", "set video rate", OFFSET(frame_rate), AV_OPT_TYPE_VIDEO_RATE, {.str="25"}, 0, INT_MAX, FLAGS },
55 { "r", "set video rate", OFFSET(frame_rate), AV_OPT_TYPE_VIDEO_RATE, {.str="25"}, 0, INT_MAX, FLAGS },
56 { "size", "set video size", OFFSET(w), AV_OPT_TYPE_IMAGE_SIZE, {.str="1024x256"}, 0, 0, FLAGS },
57 { "s", "set video size", OFFSET(w), AV_OPT_TYPE_IMAGE_SIZE, {.str="1024x256"}, 0, 0, FLAGS },
58 { "colors", "set channels colors", OFFSET(colors), AV_OPT_TYPE_STRING, {.str = "red|green|blue|yellow|orange|lime|pink|magenta|brown" }, 0, 0, FLAGS },
59 { "mode", "set output mode", OFFSET(mode), AV_OPT_TYPE_INT, {.i64 = 0 }, 0, 1, FLAGS, .unit = "mode" },
60 { "m", "set output mode", OFFSET(mode), AV_OPT_TYPE_INT, {.i64 = 0 }, 0, 1, FLAGS, .unit = "mode" },
61 { "bars", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = 0 }, 0, 0, FLAGS, .unit = "mode" },
62 { "trace", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = 1 }, 0, 0, FLAGS, .unit = "mode" },
63 { NULL }
64};
65
67
69 AVFilterFormatsConfig **cfg_in,
70 AVFilterFormatsConfig **cfg_out)
71{
77 static const enum AVPixelFormat pix_fmts[] = { AV_PIX_FMT_RGBA, AV_PIX_FMT_NONE };
78 int ret;
79
81 if ((ret = ff_formats_ref(formats, &cfg_in[0]->formats)) < 0)
82 return ret;
83
85 if ((ret = ff_formats_ref(formats, &cfg_out[0]->formats)) < 0)
86 return ret;
87
88 return 0;
89}
90
91static int config_input(AVFilterLink *inlink)
92{
93 AVFilterContext *ctx = inlink->dst;
94 AudioBitScopeContext *s = ctx->priv;
95 int ch;
96 char *colors, *saveptr = NULL;
97
98 s->nb_samples = FFMAX(1, av_rescale(inlink->sample_rate, s->frame_rate.den, s->frame_rate.num));
99 s->nb_channels = inlink->ch_layout.nb_channels;
100 s->depth = inlink->format == AV_SAMPLE_FMT_S16P ? 16 : 32;
101
102 s->fg = av_malloc_array(s->nb_channels, 4 * sizeof(*s->fg));
103 if (!s->fg)
104 return AVERROR(ENOMEM);
105
106 colors = av_strdup(s->colors);
107 if (!colors)
108 return AVERROR(ENOMEM);
109
110 for (ch = 0; ch < s->nb_channels; ch++) {
111 uint8_t fg[4] = { 0xff, 0xff, 0xff, 0xff };
112 char *color;
113
114 color = av_strtok(ch == 0 ? colors : NULL, " |", &saveptr);
115 if (color)
116 av_parse_color(fg, color, -1, ctx);
117 s->fg[4 * ch + 0] = fg[0];
118 s->fg[4 * ch + 1] = fg[1];
119 s->fg[4 * ch + 2] = fg[2];
120 s->fg[4 * ch + 3] = fg[3];
121 }
122 av_free(colors);
123
124 return 0;
125}
126
127static int config_output(AVFilterLink *outlink)
128{
129 AudioBitScopeContext *s = outlink->src->priv;
130 FilterLink *l = ff_filter_link(outlink);
131
132 outlink->w = s->w;
133 outlink->h = s->h;
134 outlink->sample_aspect_ratio = (AVRational){1,1};
135 l->frame_rate = s->frame_rate;
136 outlink->time_base = av_inv_q(l->frame_rate);
137
138 return 0;
139}
140
141#define BITCOUNTER(type, depth, one) \
142 memset(counter, 0, sizeof(s->counter)); \
143 for (int i = 0; i < nb_samples; i++) { \
144 const type x = in[i]; \
145 for (int j = 0; j < depth && x; j++) \
146 counter[j] += !!(x & (one << j)); \
147 }
148
149#define BARS(type, depth, one) \
150 for (int ch = 0; ch < inlink->ch_layout.nb_channels; ch++) { \
151 const int nb_samples = insamples->nb_samples; \
152 const type *in = (const type *)insamples->extended_data[ch]; \
153 const int w = outpicref->width / inlink->ch_layout.nb_channels; \
154 const int h = outpicref->height / depth; \
155 const uint32_t color = AV_RN32(&s->fg[4 * ch]); \
156 uint64_t *counter = s->counter; \
157 \
158 BITCOUNTER(type, depth, one) \
159 \
160 for (int b = 0; b < depth; b++) { \
161 for (int j = 1; j < h - 1; j++) { \
162 uint8_t *dst = outpicref->data[0] + (b * h + j) * outpicref->linesize[0] + w * ch * 4; \
163 const int ww = (counter[depth - b - 1] / (float)nb_samples) * (w - 1); \
164 \
165 for (int i = 0; i < ww; i++) { \
166 AV_WN32(&dst[i * 4], color); \
167 } \
168 } \
169 } \
170 }
171
172#define DO_TRACE(type, depth, one) \
173 for (int ch = 0; ch < inlink->ch_layout.nb_channels; ch++) { \
174 const int nb_samples = insamples->nb_samples; \
175 const int w = outpicref->width / inlink->ch_layout.nb_channels; \
176 const type *in = (const type *)insamples->extended_data[ch]; \
177 uint64_t *counter = s->counter; \
178 const int wb = w / depth; \
179 int wv; \
180 \
181 BITCOUNTER(type, depth, one) \
182 \
183 for (int b = 0; b < depth; b++) { \
184 uint8_t colors[4]; \
185 uint32_t color; \
186 uint8_t *dst = outpicref->data[0] + w * ch * 4 + wb * b * 4 + \
187 s->current_vpos * outpicref->linesize[0]; \
188 wv = (counter[depth - b - 1] * 255) / nb_samples; \
189 colors[0] = (wv * s->fg[ch * 4 + 0] + 127) / 255; \
190 colors[1] = (wv * s->fg[ch * 4 + 1] + 127) / 255; \
191 colors[2] = (wv * s->fg[ch * 4 + 2] + 127) / 255; \
192 colors[3] = (wv * s->fg[ch * 4 + 3] + 127) / 255; \
193 color = AV_RN32(colors); \
194 \
195 for (int x = 0; x < wb; x++) \
196 AV_WN32(&dst[x * 4], color); \
197 } \
198 }
199
200static int filter_frame(AVFilterLink *inlink, AVFrame *insamples)
201{
202 AVFilterContext *ctx = inlink->dst;
203 AVFilterLink *outlink = ctx->outputs[0];
204 AudioBitScopeContext *s = ctx->priv;
205 AVFrame *outpicref;
206 int ret;
207
208 if (s->mode == 0 || !s->outpicref) {
209 outpicref = ff_get_video_buffer(outlink, outlink->w, outlink->h);
210 if (!outpicref) {
211 av_frame_free(&insamples);
212 return AVERROR(ENOMEM);
213 }
214
215 for (int i = 0; i < outlink->h; i++)
216 memset(outpicref->data[0] + i * outpicref->linesize[0], 0, outlink->w * 4);
217 if (!s->outpicref && s->mode == 1)
218 s->outpicref = outpicref;
219 }
220
221 if (s->mode == 1) {
222 ret = ff_inlink_make_frame_writable(outlink, &s->outpicref);
223 if (ret < 0) {
224 av_frame_free(&insamples);
225 return ret;
226 }
227 outpicref = av_frame_clone(s->outpicref);
228 if (!outpicref) {
229 av_frame_free(&insamples);
230 return AVERROR(ENOMEM);
231 }
232 }
233
234 outpicref->pts = av_rescale_q(insamples->pts, inlink->time_base, outlink->time_base);
235 outpicref->duration = 1;
236 outpicref->sample_aspect_ratio = (AVRational){1,1};
237
238 switch (insamples->format) {
240 if (s->mode == 0) { BARS(uint8_t, 8, 1) } else { DO_TRACE(uint8_t, 8, 1) }
241 break;
243 if (s->mode == 0) { BARS(uint16_t, 16, 1) } else { DO_TRACE(uint16_t, 16, 1) }
244 break;
247 if (s->mode == 0) { BARS(uint32_t, 32, 1U) } else { DO_TRACE(uint32_t, 32, 1U) }
248 break;
251 if (s->mode == 0) { BARS(uint64_t, 64, 1ULL) } else { DO_TRACE(uint64_t, 64, 1ULL) }
252 break;
253 }
254
255 s->current_vpos++;
256 if (s->current_vpos >= outlink->h)
257 s->current_vpos = 0;
258 av_frame_free(&insamples);
259
260 return ff_filter_frame(outlink, outpicref);
261}
262
264{
265 AVFilterLink *inlink = ctx->inputs[0];
266 AVFilterLink *outlink = ctx->outputs[0];
267 AudioBitScopeContext *s = ctx->priv;
268 AVFrame *in;
269 int ret;
270
271 FF_FILTER_FORWARD_STATUS_BACK(outlink, inlink);
272
273 ret = ff_inlink_consume_samples(inlink, s->nb_samples, s->nb_samples, &in);
274 if (ret < 0)
275 return ret;
276 if (ret > 0)
277 return filter_frame(inlink, in);
278
279 FF_FILTER_FORWARD_STATUS(inlink, outlink);
280 FF_FILTER_FORWARD_WANTED(outlink, inlink);
281
282 return FFERROR_NOT_READY;
283}
284
286{
287 AudioBitScopeContext *s = ctx->priv;
288
289 av_frame_free(&s->outpicref);
290}
291
292static const AVFilterPad inputs[] = {
293 {
294 .name = "default",
295 .type = AVMEDIA_TYPE_AUDIO,
296 .config_props = config_input,
297 },
298};
299
300static const AVFilterPad outputs[] = {
301 {
302 .name = "default",
303 .type = AVMEDIA_TYPE_VIDEO,
304 .config_props = config_output,
305 },
306};
307
309 .p.name = "abitscope",
310 .p.description = NULL_IF_CONFIG_SMALL("Convert input audio to audio bit scope video output."),
311 .p.priv_class = &abitscope_class,
312 .priv_size = sizeof(AudioBitScopeContext),
316 .uninit = uninit,
317 .activate = activate,
318};
static enum AVSampleFormat sample_fmts[]
Definition adpcmenc.c:933
static int query_formats(const AVFilterContext *ctx, AVFilterFormatsConfig **cfg_in, AVFilterFormatsConfig **cfg_out)
Definition aeval.c:246
static const AVFilterPad inputs[]
Definition af_aap.c:299
static const AVFilterPad outputs[]
Definition af_aap.c:310
static int config_input(AVFilterLink *inlink)
const FFFilter ff_avf_abitscope
static AVFormatContext * ctx
static int filter_frame(AVFilterLink *inlink, AVFrame *insamples)
#define BARS(type, depth, one)
static int config_input(AVFilterLink *inlink)
static int query_formats(const AVFilterContext *ctx, AVFilterFormatsConfig **cfg_in, AVFilterFormatsConfig **cfg_out)
static int activate(AVFilterContext *ctx)
static av_cold void uninit(AVFilterContext *ctx)
#define DO_TRACE(type, depth, one)
#define OFFSET(x)
static int config_output(AVFilterLink *outlink)
static const AVOption abitscope_options[]
int ff_filter_frame(AVFilterLink *link, AVFrame *frame)
Send a frame of data to the next filter.
Definition avfilter.c:1068
int ff_inlink_consume_samples(AVFilterLink *link, unsigned min, unsigned max, AVFrame **rframe)
Take samples from the link's FIFO and update the link's stats.
Definition avfilter.c:1540
int ff_inlink_make_frame_writable(AVFilterLink *link, AVFrame **rframe)
Make sure a frame is writable.
Definition avfilter.c:1567
Main libavfilter public API header.
#define i(width, name, range_min, range_max)
Definition cbs_h264.c:63
#define s(width, name)
Definition cbs_vp9.c:198
#define FLAGS
Definition cmdutils.c:598
#define NULL
Definition coverity.c:32
int ff_formats_ref(AVFilterFormats *f, AVFilterFormats **ref)
Add ref as a new reference to formats.
Definition formats.c:756
av_warn_unused_result AVFilterFormats * ff_make_sample_format_list(const enum AVSampleFormat *fmts)
Create a list of supported sample formats.
av_warn_unused_result AVFilterFormats * ff_make_pixel_format_list(const enum AVPixelFormat *fmts)
Create a list of supported pixel formats.
@ AV_OPT_TYPE_IMAGE_SIZE
Underlying C type is two consecutive integers.
Definition opt.h:302
@ AV_OPT_TYPE_CONST
Special option type for declaring named constants.
Definition opt.h:298
@ AV_OPT_TYPE_VIDEO_RATE
Underlying C type is AVRational.
Definition opt.h:314
@ AV_OPT_TYPE_INT
Underlying C type is int.
Definition opt.h:258
@ AV_OPT_TYPE_STRING
Underlying C type is a uint8_t* that is either NULL or points to a C string allocated with the av_mal...
Definition opt.h:275
#define AVERROR(e)
Definition error.h:45
void av_frame_free(AVFrame **frame)
Free the frame and any dynamically allocated objects in it, e.g.
Definition frame.c:64
AVFrame * av_frame_clone(const AVFrame *src)
Create a new frame that references the same data as src.
Definition frame.c:483
static av_always_inline AVRational av_inv_q(AVRational q)
Invert a rational.
Definition rational.h:159
int64_t av_rescale(int64_t a, int64_t b, int64_t c)
Rescale a 64-bit integer with rounding to nearest.
int64_t av_rescale_q(int64_t a, AVRational bq, AVRational cq)
Rescale a 64-bit integer by 2 rational numbers.
@ AVMEDIA_TYPE_AUDIO
Definition avutil.h:201
@ AVMEDIA_TYPE_VIDEO
Definition avutil.h:200
AVSampleFormat
Audio sample formats.
Definition samplefmt.h:55
@ AV_SAMPLE_FMT_FLTP
float, planar
Definition samplefmt.h:66
@ AV_SAMPLE_FMT_S16P
signed 16 bits, planar
Definition samplefmt.h:64
@ AV_SAMPLE_FMT_U8P
unsigned 8 bits, planar
Definition samplefmt.h:63
@ AV_SAMPLE_FMT_S32P
signed 32 bits, planar
Definition samplefmt.h:65
@ AV_SAMPLE_FMT_NONE
Definition samplefmt.h:56
@ AV_SAMPLE_FMT_DBLP
double, planar
Definition samplefmt.h:67
@ AV_SAMPLE_FMT_S64P
signed 64 bits, planar
Definition samplefmt.h:69
char * av_strtok(char *s, const char *delim, char **saveptr)
Split the string into several tokens which can be accessed by successive calls to av_strtok().
Definition avstring.c:179
static av_cold void uninit(AVBitStreamFilterContext *ctx)
static int activate(AVBitStreamFilterContext *ctx)
static int config_output(AVBitStreamFilterLink *outlink)
#define FILTER_INPUTS(array)
Definition filters.h:264
#define FILTER_OUTPUTS(array)
Definition filters.h:265
#define FF_FILTER_FORWARD_WANTED(outlink, inlink)
Forward the frame_wanted_out flag from an output link to an input link.
Definition filters.h:694
#define FF_FILTER_FORWARD_STATUS(inlink, outlink)
Acknowledge the status on an input link and forward it to an output link.
Definition filters.h:666
#define FFERROR_NOT_READY
Filters implementation helper functions and internal structures.
Definition filters.h:34
#define FF_FILTER_FORWARD_STATUS_BACK(outlink, inlink)
Forward the status on an output link to an input link.
Definition filters.h:639
static FilterLink * ff_filter_link(AVFilterLink *link)
Definition filters.h:199
#define AVFILTER_DEFINE_CLASS(fname)
Definition filters.h:478
#define FILTER_QUERY_FUNC2(func)
Definition filters.h:241
#define av_cold
Definition attributes.h:117
#define NULL_IF_CONFIG_SMALL(x)
Return NULL if CONFIG_SMALL is true, otherwise the argument without modification.
Definition internal.h:88
static enum AVPixelFormat pix_fmts[]
Definition libkvazaar.c:296
uint8_t w
Definition llvidencdsp.c:39
#define FFMAX(a, b)
Definition macros.h:47
Memory handling functions.
#define av_strdup(s)
Definition ops_static.c:55
AVOptions.
int av_parse_color(uint8_t *rgba_color, const char *color_string, int slen, void *log_ctx)
Put the RGBA values that correspond to color_string in rgba_color.
Definition parseutils.c:359
misc parsing utilities
AVPixelFormat
Pixel format.
Definition pixfmt.h:71
@ AV_PIX_FMT_NONE
Definition pixfmt.h:72
@ AV_PIX_FMT_RGBA
packed RGBA 8:8:8:8, 32bpp, RGBARGBA...
Definition pixfmt.h:100
formats
Definition signature.h:47
int nb_channels
Number of channels in this layout.
Describe the class of an AVClass context structure.
Definition log.h:76
An instance of a filter.
Definition avfilter.h:273
void * priv
private data for use by the filter
Definition avfilter.h:288
Lists of formats / etc.
Definition avfilter.h:120
A list of supported formats for one end of a filter link.
Definition formats.h:64
A filter pad used for either input or output.
Definition filters.h:40
This structure describes decoded (raw) audio or video data.
Definition frame.h:472
int64_t pts
Presentation timestamp in time_base units (time when frame should be shown to user).
Definition frame.h:574
uint8_t * data[AV_NUM_DATA_POINTERS]
pointer to the picture/channel planes.
Definition frame.h:493
AVRational sample_aspect_ratio
Sample aspect ratio for the video frame, 0/1 if unknown/unspecified.
Definition frame.h:569
int linesize[AV_NUM_DATA_POINTERS]
For video, a positive or negative value, which is typically indicating the size in bytes of each pict...
Definition frame.h:517
int64_t duration
Duration of the frame, in the same units as pts.
Definition frame.h:820
int format
format of the frame, -1 if unknown or unset Values correspond to enum AVPixelFormat for video frames,...
Definition frame.h:559
AVOption.
Definition opt.h:428
Rational number (pair of numerator and denominator).
Definition rational.h:58
Definition swscale.c:71
#define av_free(p)
#define av_malloc_array(a, b)
AVFrame * ff_get_video_buffer(AVFilterLink *link, int w, int h)
Request a picture buffer with a specific set of permissions.
Definition video.c:89