| @@ -34,13 +34,17 @@ typedef struct AudioBitScopeContext { · 33 unmodified lines |
| 34 | int w, h; | 34 | int w, h; |
| 35 | AVRational frame_rate; | 35 | AVRational frame_rate; |
| 36 | char *colors; | 36 | char *colors; |
| | 37 | int mode; |
| 37 | | 38 | |
| 38 | int nb_channels; | 39 | int nb_channels; |
| 39 | int nb_samples; | 40 | int nb_samples; |
| 40 | int depth; | 41 | int depth; |
| | 42 | int current_vpos; |
| 41 | uint8_t *fg; | 43 | uint8_t *fg; |
| 42 | | 44 | |
| 43 | uint64_t counter[64]; | 45 | uint64_t counter[64]; |
| | 46 | |
| | 47 | AVFrame *outpicref; |
| 44 | } AudioBitScopeContext; | 48 | } AudioBitScopeContext; |
| 45 | | 49 | |
| 46 | #define OFFSET(x) offsetof(AudioBitScopeContext, x) | 50 | #define OFFSET(x) offsetof(AudioBitScopeContext, x) |
| @@ -52,6 +56,10 @@ static const AVOption abitscope_options[] = { · 5 unmodified lines |
| 52 | { "size", "set video size", OFFSET(w), AV_OPT_TYPE_IMAGE_SIZE, {.str="1024x256"}, 0, 0, FLAGS }, | 56 | { "size", "set video size", OFFSET(w), AV_OPT_TYPE_IMAGE_SIZE, {.str="1024x256"}, 0, 0, FLAGS }, |
| 53 | { "s", "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 }, |
| 54 | { "colors", "set channels colors", OFFSET(colors), AV_OPT_TYPE_STRING, {.str = "red|green|blue|yellow|orange|lime|pink|magenta|brown" }, 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, "mode" }, |
| | 60 | { "m", "set output mode", OFFSET(mode), AV_OPT_TYPE_INT, {.i64 = 0 }, 0, 1, FLAGS, "mode" }, |
| | 61 | { "bars", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = 0 }, 0, 0, FLAGS, "mode" }, |
| | 62 | { "trace", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = 1 }, 0, 0, FLAGS, "mode" }, |
| 55 | { NULL } | 63 | { NULL } |
| 56 | }; | 64 | }; |
| 57 | | 65 | |
| @@ -146,75 +154,99 @@ static void count_bits(AudioBitScopeContext *s, uint32_t sample, int max) · 88 unmodified lines |
| 146 | } | 154 | } |
| 147 | } | 155 | } |
| 148 | | 156 | |
| | 157 | |
| | 158 | #define BARS(type, depth) \ |
| | 159 | for (int ch = 0; ch < inlink->channels; ch++) { \ |
| | 160 | const type *in = (const type *)insamples->extended_data[ch]; \ |
| | 161 | const int w = outpicref->width / inlink->channels; \ |
| | 162 | const int h = outpicref->height / depth; \ |
| | 163 | const uint32_t color = AV_RN32(&s->fg[4 * ch]); \ |
| | 164 | \ |
| | 165 | memset(s->counter, 0, sizeof(s->counter)); \ |
| | 166 | for (int i = 0; i < insamples->nb_samples; i++) \ |
| | 167 | count_bits(s, in[i], depth); \ |
| | 168 | \ |
| | 169 | for (int b = 0; b < depth; b++) { \ |
| | 170 | for (int j = 1; j < h - 1; j++) { \ |
| | 171 | uint8_t *dst = outpicref->data[0] + (b * h + j) * outpicref->linesize[0] + w * ch * 4; \ |
| | 172 | const int ww = (s->counter[depth - b - 1] / (float)insamples->nb_samples) * (w - 1); \ |
| | 173 | \ |
| | 174 | for (int i = 0; i < ww; i++) { \ |
| | 175 | AV_WN32(&dst[i * 4], color); \ |
| | 176 | } \ |
| | 177 | } \ |
| | 178 | } \ |
| | 179 | } |
| | 180 | |
| | 181 | #define TRACE(type, depth) \ |
| | 182 | for (int ch = 0; ch < inlink->channels; ch++) { \ |
| | 183 | const int w = outpicref->width / inlink->channels; \ |
| | 184 | const type *in = (const type *)insamples->extended_data[ch]; \ |
| | 185 | const int wb = w / depth; \ |
| | 186 | int wv; \ |
| | 187 | \ |
| | 188 | memset(s->counter, 0, sizeof(s->counter)); \ |
| | 189 | for (int i = 0; i < insamples->nb_samples; i++) \ |
| | 190 | count_bits(s, in[i], depth); \ |
| | 191 | \ |
| | 192 | for (int b = 0; b < depth; b++) { \ |
| | 193 | uint8_t colors[4]; \ |
| | 194 | uint32_t color; \ |
| | 195 | uint8_t *dst = outpicref->data[0] + w * ch * 4 + wb * b * 4 + \ |
| | 196 | s->current_vpos * outpicref->linesize[0]; \ |
| | 197 | wv = (s->counter[depth - b - 1] * 255) / insamples->nb_samples; \ |
| | 198 | colors[0] = (wv * s->fg[ch * 4 + 0] + 127) / 255; \ |
| | 199 | colors[1] = (wv * s->fg[ch * 4 + 1] + 127) / 255; \ |
| | 200 | colors[2] = (wv * s->fg[ch * 4 + 2] + 127) / 255; \ |
| | 201 | colors[3] = (wv * s->fg[ch * 4 + 3] + 127) / 255; \ |
| | 202 | color = AV_RN32(colors); \ |
| | 203 | \ |
| | 204 | for (int x = 0; x < wb; x++) \ |
| | 205 | AV_WN32(&dst[x * 4], color); \ |
| | 206 | } \ |
| | 207 | } |
| | 208 | |
| 149 | static int filter_frame(AVFilterLink *inlink, AVFrame *insamples) | 209 | static int filter_frame(AVFilterLink *inlink, AVFrame *insamples) |
| 150 | { | 210 | { |
| 151 | AVFilterContext *ctx = inlink->dst; | 211 | AVFilterContext *ctx = inlink->dst; |
| 152 | AVFilterLink *outlink = ctx->outputs[0]; | 212 | AVFilterLink *outlink = ctx->outputs[0]; |
| 153 | AudioBitScopeContext *s = ctx->priv; | 213 | AudioBitScopeContext *s = ctx->priv; |
| 154 | AVFrame *outpicref; | 214 | AVFrame *outpicref; |
| 155 | int ch, i, j, b; | | |
| 156 | | 215 | |
| 157 | outpicref = ff_get_video_buffer(outlink, outlink->w, outlink->h); | 216 | if (s->mode == 0 || !s->outpicref) { |
| 158 | if (!outpicref) { | 217 | outpicref = ff_get_video_buffer(outlink, outlink->w, outlink->h); |
| 159 | av_frame_free(&insamples); | 218 | if (!outpicref) { |
| 160 | return AVERROR(ENOMEM); | 219 | av_frame_free(&insamples); |
| | 220 | return AVERROR(ENOMEM); |
| | 221 | } |
| | 222 | |
| | 223 | for (int i = 0; i < outlink->h; i++) |
| | 224 | memset(outpicref->data[0] + i * outpicref->linesize[0], 0, outlink->w * 4); |
| | 225 | if (!s->outpicref && s->mode == 1) |
| | 226 | s->outpicref = outpicref; |
| 161 | } | 227 | } |
| 162 | | 228 | |
| 163 | for (i = 0; i < outlink->h; i++) | 229 | if (s->mode == 1) { |
| 164 | memset(outpicref->data[0] + i * outpicref->linesize[0], 0, outlink->w * 4); | 230 | outpicref = av_frame_clone(s->outpicref); |
| | 231 | if (!outpicref) |
| | 232 | return AVERROR(ENOMEM); |
| | 233 | } |
| 165 | | 234 | |
| 166 | outpicref->pts = insamples->pts; | 235 | outpicref->pts = insamples->pts; |
| 167 | outpicref->sample_aspect_ratio = (AVRational){1,1}; | 236 | outpicref->sample_aspect_ratio = (AVRational){1,1}; |
| 168 | | 237 | |
| 169 | switch (insamples->format) { | 238 | switch (insamples->format) { |
| 170 | case AV_SAMPLE_FMT_S16P: | 239 | case AV_SAMPLE_FMT_S16P: |
| 171 | for (ch = 0; ch < inlink->channels; ch++) { | 240 | if (s->mode == 0) { BARS(uint16_t, 16) } else { TRACE(uint16_t, 16) } |
| 172 | uint16_t *in = (uint16_t *)insamples->extended_data[ch]; | | |
| 173 | int w = outpicref->width / inlink->channels; | | |
| 174 | int h = outpicref->height / 16; | | |
| 175 | uint32_t color = AV_RN32(&s->fg[4 * ch]); | | |
| 176 | | | |
| 177 | memset(s->counter, 0, sizeof(s->counter)); | | |
| 178 | for (i = 0; i < insamples->nb_samples; i++) | | |
| 179 | count_bits(s, in[i], 16); | | |
| 180 | | | |
| 181 | for (b = 0; b < 16; b++) { | | |
| 182 | for (j = 1; j < h - 1; j++) { | | |
| 183 | uint8_t *dst = outpicref->data[0] + (b * h + j) * outpicref->linesize[0] + w * ch * 4; | | |
| 184 | int ww = (s->counter[16 - b - 1] / (float)insamples->nb_samples) * (w - 1); | | |
| 185 | | | |
| 186 | for (i = 0; i < ww; i++) { | | |
| 187 | AV_WN32(&dst[i * 4], color); | | |
| 188 | } | | |
| 189 | } | | |
| 190 | } | | |
| 191 | } | | |
| 192 | break; | 241 | break; |
| 193 | case AV_SAMPLE_FMT_S32P: | 242 | case AV_SAMPLE_FMT_S32P: |
| 194 | for (ch = 0; ch < inlink->channels; ch++) { | 243 | if (s->mode == 0) { BARS(uint32_t, 32) } else { TRACE(uint32_t, 32) } |
| 195 | uint32_t *in = (uint32_t *)insamples->extended_data[ch]; | | |
| 196 | int w = outpicref->width / inlink->channels; | | |
| 197 | int h = outpicref->height / 32; | | |
| 198 | uint32_t color = AV_RN32(&s->fg[4 * ch]); | | |
| 199 | | | |
| 200 | memset(s->counter, 0, sizeof(s->counter)); | | |
| 201 | for (i = 0; i < insamples->nb_samples; i++) | | |
| 202 | count_bits(s, in[i], 32); | | |
| 203 | | | |
| 204 | for (b = 0; b < 32; b++) { | | |
| 205 | for (j = 1; j < h - 1; j++) { | | |
| 206 | uint8_t *dst = outpicref->data[0] + (b * h + j) * outpicref->linesize[0] + w * ch * 4; | | |
| 207 | int ww = (s->counter[32 - b - 1] / (float)insamples->nb_samples) * (w - 1); | | |
| 208 | | | |
| 209 | for (i = 0; i < ww; i++) { | | |
| 210 | AV_WN32(&dst[i * 4], color); | | |
| 211 | } | | |
| 212 | } | | |
| 213 | } | | |
| 214 | } | | |
| 215 | break; | 244 | break; |
| 216 | } | 245 | } |
| 217 | | 246 | |
| | 247 | s->current_vpos++; |
| | 248 | if (s->current_vpos >= outlink->h) |
| | 249 | s->current_vpos = 0; |
| 218 | av_frame_free(&insamples); | 250 | av_frame_free(&insamples); |
| 219 | | 251 | |
| 220 | return ff_filter_frame(outlink, outpicref); | 252 | return ff_filter_frame(outlink, outpicref); |
| @@ -242,6 +274,13 @@ static int activate(AVFilterContext *ctx) · 21 unmodified lines |
| 242 | return FFERROR_NOT_READY; | 274 | return FFERROR_NOT_READY; |
| 243 | } | 275 | } |
| 244 | | 276 | |
| | 277 | static av_cold void uninit(AVFilterContext *ctx) |
| | 278 | { |
| | 279 | AudioBitScopeContext *s = ctx->priv; |
| | 280 | |
| | 281 | av_frame_free(&s->outpicref); |
| | 282 | } |
| | 283 | |
| 245 | static const AVFilterPad inputs[] = { | 284 | static const AVFilterPad inputs[] = { |
| 246 | { | 285 | { |
| 247 | .name = "default", | 286 | .name = "default", |
| @@ -265,6 +304,7 @@ const AVFilter ff_avf_abitscope = { · 17 unmodified lines |
| 265 | FILTER_INPUTS(inputs), | 304 | FILTER_INPUTS(inputs), |
| 266 | FILTER_OUTPUTS(outputs), | 305 | FILTER_OUTPUTS(outputs), |
| 267 | FILTER_QUERY_FUNC(query_formats), | 306 | FILTER_QUERY_FUNC(query_formats), |
| | 307 | .uninit = uninit, |
| 268 | .activate = activate, | 308 | .activate = activate, |
| 269 | .priv_class = &abitscope_class, | 309 | .priv_class = &abitscope_class, |
| 270 | }; | 310 | }; |