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
31
38
44
46
49
50 #define OFFSET(x) offsetof(AudioBitScopeContext, x)
51 #define FLAGS AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_VIDEO_PARAM
52
58 {
"colors",
"set channels colors",
OFFSET(colors),
AV_OPT_TYPE_STRING, {.str =
"red|green|blue|yellow|orange|lime|pink|magenta|brown" }, 0, 0,
FLAGS },
64 };
65
67
71 {
79
83
87
88 return 0;
89 }
90
92 {
95 int ch;
96 char *colors, *saveptr =
NULL;
97
99 s->nb_channels =
inlink->ch_layout.nb_channels;
101
105
107 if (!colors)
109
110 for (ch = 0; ch <
s->nb_channels; ch++) {
111 uint8_t fg[4] = { 0xff, 0xff, 0xff, 0xff };
113
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 }
123
124 return 0;
125 }
126
128 {
131
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
201 {
207
208 if (
s->mode == 0 || !
s->outpicref) {
210 if (!outpicref) {
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
226 }
228 if (!outpicref) {
231 }
232 }
233
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, 1
U) }
else {
DO_TRACE(uint32_t, 32, 1
U) }
248 break;
251 if (
s->mode == 0) {
BARS(uint64_t, 64, 1ULL) }
else {
DO_TRACE(uint64_t, 64, 1ULL) }
252 break;
253 }
254
256 if (
s->current_vpos >= outlink->
h)
259
261 }
262
264 {
270
272
278
281
283 }
284
286 {
288
290 }
291
293 {
297 },
298 };
299
301 {
305 },
306 };
307
309 .
p.
name =
"abitscope",
311 .p.priv_class = &abitscope_class,
318 };