| @@ -32,6 +32,10 @@ · 31 unmodified lines |
| 32 | #include "internal.h" | 32 | #include "internal.h" |
| 33 | #include "video.h" | 33 | #include "video.h" |
| 34 | | 34 | |
| | 35 | typedef struct CacheItem { |
| | 36 | int64_t previous_pts_us; |
| | 37 | } CacheItem; |
| | 38 | |
| 35 | typedef struct GraphMonitorContext { | 39 | typedef struct GraphMonitorContext { |
| 36 | const AVClass *class; | 40 | const AVClass *class; |
| 37 | | 41 | |
| @@ -49,6 +53,10 @@ typedef struct GraphMonitorContext { · 11 unmodified lines |
| 49 | uint8_t green[4]; | 53 | uint8_t green[4]; |
| 50 | uint8_t blue[4]; | 54 | uint8_t blue[4]; |
| 51 | uint8_t bg[4]; | 55 | uint8_t bg[4]; |
| | 56 | |
| | 57 | CacheItem *cache; |
| | 58 | unsigned int cache_size; |
| | 59 | unsigned int cache_index; |
| 52 | } GraphMonitorContext; | 60 | } GraphMonitorContext; |
| 53 | | 61 | |
| 54 | enum { | 62 | enum { |
| @@ -64,6 +72,10 @@ enum { · 9 unmodified lines |
| 64 | MODE_EOF = 1 << 9, | 72 | MODE_EOF = 1 << 9, |
| 65 | MODE_SCIN = 1 << 10, | 73 | MODE_SCIN = 1 << 10, |
| 66 | MODE_SCOUT = 1 << 11, | 74 | MODE_SCOUT = 1 << 11, |
| | 75 | MODE_PTS_DELTA = 1 << 12, |
| | 76 | MODE_TIME_DELTA = 1 << 13, |
| | 77 | MODE_FC_DELTA = 1 << 14, |
| | 78 | MODE_SC_DELTA = 1 << 15, |
| 67 | }; | 79 | }; |
| 68 | | 80 | |
| 69 | #define OFFSET(x) offsetof(GraphMonitorContext, x) | 81 | #define OFFSET(x) offsetof(GraphMonitorContext, x) |
| @@ -83,8 +95,11 @@ static const AVOption graphmonitor_options[] = { · 13 unmodified lines |
| 83 | { "queue", NULL, 0, AV_OPT_TYPE_CONST, {.i64=MODE_QUEUE}, 0, 0, VF, "flags" }, | 95 | { "queue", NULL, 0, AV_OPT_TYPE_CONST, {.i64=MODE_QUEUE}, 0, 0, VF, "flags" }, |
| 84 | { "frame_count_in", NULL, 0, AV_OPT_TYPE_CONST, {.i64=MODE_FCOUT}, 0, 0, VF, "flags" }, | 96 | { "frame_count_in", NULL, 0, AV_OPT_TYPE_CONST, {.i64=MODE_FCOUT}, 0, 0, VF, "flags" }, |
| 85 | { "frame_count_out", NULL, 0, AV_OPT_TYPE_CONST, {.i64=MODE_FCIN}, 0, 0, VF, "flags" }, | 97 | { "frame_count_out", NULL, 0, AV_OPT_TYPE_CONST, {.i64=MODE_FCIN}, 0, 0, VF, "flags" }, |
| | 98 | { "frame_count_delta",NULL, 0, AV_OPT_TYPE_CONST, {.i64=MODE_FC_DELTA},0, 0, VF, "flags" }, |
| 86 | { "pts", NULL, 0, AV_OPT_TYPE_CONST, {.i64=MODE_PTS}, 0, 0, VF, "flags" }, | 99 | { "pts", NULL, 0, AV_OPT_TYPE_CONST, {.i64=MODE_PTS}, 0, 0, VF, "flags" }, |
| | 100 | { "pts_delta", NULL, 0, AV_OPT_TYPE_CONST, {.i64=MODE_PTS_DELTA},0,0, VF, "flags" }, |
| 87 | { "time", NULL, 0, AV_OPT_TYPE_CONST, {.i64=MODE_TIME}, 0, 0, VF, "flags" }, | 101 | { "time", NULL, 0, AV_OPT_TYPE_CONST, {.i64=MODE_TIME}, 0, 0, VF, "flags" }, |
| | 102 | { "time_delta", NULL, 0, AV_OPT_TYPE_CONST, {.i64=MODE_TIME_DELTA},0,0,VF, "flags" }, |
| 88 | { "timebase", NULL, 0, AV_OPT_TYPE_CONST, {.i64=MODE_TB}, 0, 0, VF, "flags" }, | 103 | { "timebase", NULL, 0, AV_OPT_TYPE_CONST, {.i64=MODE_TB}, 0, 0, VF, "flags" }, |
| 89 | { "format", NULL, 0, AV_OPT_TYPE_CONST, {.i64=MODE_FMT}, 0, 0, VF, "flags" }, | 104 | { "format", NULL, 0, AV_OPT_TYPE_CONST, {.i64=MODE_FMT}, 0, 0, VF, "flags" }, |
| 90 | { "size", NULL, 0, AV_OPT_TYPE_CONST, {.i64=MODE_SIZE}, 0, 0, VF, "flags" }, | 105 | { "size", NULL, 0, AV_OPT_TYPE_CONST, {.i64=MODE_SIZE}, 0, 0, VF, "flags" }, |
| @@ -92,11 +107,24 @@ static const AVOption graphmonitor_options[] = { · 1 unmodified line |
| 92 | { "eof", NULL, 0, AV_OPT_TYPE_CONST, {.i64=MODE_EOF}, 0, 0, VF, "flags" }, | 107 | { "eof", NULL, 0, AV_OPT_TYPE_CONST, {.i64=MODE_EOF}, 0, 0, VF, "flags" }, |
| 93 | { "sample_count_in", NULL, 0, AV_OPT_TYPE_CONST, {.i64=MODE_SCOUT}, 0, 0, VF, "flags" }, | 108 | { "sample_count_in", NULL, 0, AV_OPT_TYPE_CONST, {.i64=MODE_SCOUT}, 0, 0, VF, "flags" }, |
| 94 | { "sample_count_out", NULL, 0, AV_OPT_TYPE_CONST, {.i64=MODE_SCIN}, 0, 0, VF, "flags" }, | 109 | { "sample_count_out", NULL, 0, AV_OPT_TYPE_CONST, {.i64=MODE_SCIN}, 0, 0, VF, "flags" }, |
| | 110 | { "sample_count_delta",NULL,0, AV_OPT_TYPE_CONST, {.i64=MODE_SC_DELTA},0, 0, VF, "flags" }, |
| 95 | { "rate", "set video rate", OFFSET(frame_rate), AV_OPT_TYPE_VIDEO_RATE, {.str = "25"}, 0, INT_MAX, VF }, | 111 | { "rate", "set video rate", OFFSET(frame_rate), AV_OPT_TYPE_VIDEO_RATE, {.str = "25"}, 0, INT_MAX, VF }, |
| 96 | { "r", "set video rate", OFFSET(frame_rate), AV_OPT_TYPE_VIDEO_RATE, {.str = "25"}, 0, INT_MAX, VF }, | 112 | { "r", "set video rate", OFFSET(frame_rate), AV_OPT_TYPE_VIDEO_RATE, {.str = "25"}, 0, INT_MAX, VF }, |
| 97 | { NULL } | 113 | { NULL } |
| 98 | }; | 114 | }; |
| 99 | | 115 | |
| | 116 | static av_cold int init(AVFilterContext *ctx) |
| | 117 | { |
| | 118 | GraphMonitorContext *s = ctx->priv; |
| | 119 | |
| | 120 | s->cache = av_fast_realloc(NULL, &s->cache_size, |
| | 121 | 8192 * sizeof(*(s->cache))); |
| | 122 | if (!s->cache) |
| | 123 | return AVERROR(ENOMEM); |
| | 124 | |
| | 125 | return 0; |
| | 126 | } |
| | 127 | |
| 100 | static int query_formats(AVFilterContext *ctx) | 128 | static int query_formats(AVFilterContext *ctx) |
| 101 | { | 129 | { |
| 102 | AVFilterLink *outlink = ctx->outputs[0]; | 130 | AVFilterLink *outlink = ctx->outputs[0]; |
| @@ -173,12 +201,14 @@ static int filter_have_queued(AVFilterContext *filter) · 70 unmodified lines |
| 173 | return 0; | 201 | return 0; |
| 174 | } | 202 | } |
| 175 | | 203 | |
| 176 | static void draw_items(AVFilterContext *ctx, AVFrame *out, | 204 | static int draw_items(AVFilterContext *ctx, AVFrame *out, |
| 177 | int xpos, int ypos, | 205 | int xpos, int ypos, |
| 178 | AVFilterLink *l, | 206 | AVFilterLink *l, |
| 179 | size_t frames) | 207 | size_t frames) |
| 180 | { | 208 | { |
| 181 | GraphMonitorContext *s = ctx->priv; | 209 | GraphMonitorContext *s = ctx->priv; |
| | 210 | int64_t previous_pts_us = s->cache[s->cache_index].previous_pts_us; |
| | 211 | int64_t current_pts_us = l->current_pts_us; |
| 182 | char buffer[1024] = { 0 }; | 212 | char buffer[1024] = { 0 }; |
| 183 | | 213 | |
| 184 | if (s->flags & MODE_FMT) { | 214 | if (s->flags & MODE_FMT) { |
| @@ -233,6 +263,11 @@ static void draw_items(AVFilterContext *ctx, AVFrame *out, · 48 unmodified lines |
| 233 | drawtext(out, xpos, ypos, buffer, s->white); | 263 | drawtext(out, xpos, ypos, buffer, s->white); |
| 234 | xpos += strlen(buffer) * 8; | 264 | xpos += strlen(buffer) * 8; |
| 235 | } | 265 | } |
| | 266 | if (s->flags & MODE_FC_DELTA) { |
| | 267 | snprintf(buffer, sizeof(buffer)-1, " | delta: %"PRId64, l->frame_count_in - l->frame_count_out); |
| | 268 | drawtext(out, xpos, ypos, buffer, s->white); |
| | 269 | xpos += strlen(buffer) * 8; |
| | 270 | } |
| 236 | if (s->flags & MODE_SCIN) { | 271 | if (s->flags & MODE_SCIN) { |
| 237 | snprintf(buffer, sizeof(buffer)-1, " | sin: %"PRId64, l->sample_count_in); | 272 | snprintf(buffer, sizeof(buffer)-1, " | sin: %"PRId64, l->sample_count_in); |
| 238 | drawtext(out, xpos, ypos, buffer, s->white); | 273 | drawtext(out, xpos, ypos, buffer, s->white); |
| @@ -243,13 +278,28 @@ static void draw_items(AVFilterContext *ctx, AVFrame *out, · 4 unmodified lines |
| 243 | drawtext(out, xpos, ypos, buffer, s->white); | 278 | drawtext(out, xpos, ypos, buffer, s->white); |
| 244 | xpos += strlen(buffer) * 8; | 279 | xpos += strlen(buffer) * 8; |
| 245 | } | 280 | } |
| | 281 | if (s->flags & MODE_SC_DELTA) { |
| | 282 | snprintf(buffer, sizeof(buffer)-1, " | sdelta: %"PRId64, l->sample_count_in - l->sample_count_out); |
| | 283 | drawtext(out, xpos, ypos, buffer, s->white); |
| | 284 | xpos += strlen(buffer) * 8; |
| | 285 | } |
| 246 | if (s->flags & MODE_PTS) { | 286 | if (s->flags & MODE_PTS) { |
| 247 | snprintf(buffer, sizeof(buffer)-1, " | pts: %s", av_ts2str(l->current_pts_us)); | 287 | snprintf(buffer, sizeof(buffer)-1, " | pts: %s", av_ts2str(current_pts_us)); |
| | 288 | drawtext(out, xpos, ypos, buffer, s->white); |
| | 289 | xpos += strlen(buffer) * 8; |
| | 290 | } |
| | 291 | if (s->flags & MODE_PTS_DELTA) { |
| | 292 | snprintf(buffer, sizeof(buffer)-1, " | pts_delta: %s", av_ts2str(current_pts_us - previous_pts_us)); |
| 248 | drawtext(out, xpos, ypos, buffer, s->white); | 293 | drawtext(out, xpos, ypos, buffer, s->white); |
| 249 | xpos += strlen(buffer) * 8; | 294 | xpos += strlen(buffer) * 8; |
| 250 | } | 295 | } |
| 251 | if (s->flags & MODE_TIME) { | 296 | if (s->flags & MODE_TIME) { |
| 252 | snprintf(buffer, sizeof(buffer)-1, " | time: %s", av_ts2timestr(l->current_pts_us, &AV_TIME_BASE_Q)); | 297 | snprintf(buffer, sizeof(buffer)-1, " | time: %s", av_ts2timestr(current_pts_us, &AV_TIME_BASE_Q)); |
| | 298 | drawtext(out, xpos, ypos, buffer, s->white); |
| | 299 | xpos += strlen(buffer) * 8; |
| | 300 | } |
| | 301 | if (s->flags & MODE_TIME_DELTA) { |
| | 302 | snprintf(buffer, sizeof(buffer)-1, " | time_delta: %s", av_ts2timestr(current_pts_us - previous_pts_us, &AV_TIME_BASE_Q)); |
| 253 | drawtext(out, xpos, ypos, buffer, s->white); | 303 | drawtext(out, xpos, ypos, buffer, s->white); |
| 254 | xpos += strlen(buffer) * 8; | 304 | xpos += strlen(buffer) * 8; |
| 255 | } | 305 | } |
| @@ -258,6 +308,19 @@ static void draw_items(AVFilterContext *ctx, AVFrame *out, · 2 unmodified lines |
| 258 | drawtext(out, xpos, ypos, buffer, s->blue); | 308 | drawtext(out, xpos, ypos, buffer, s->blue); |
| 259 | xpos += strlen(buffer) * 8; | 309 | xpos += strlen(buffer) * 8; |
| 260 | } | 310 | } |
| | 311 | |
| | 312 | s->cache[s->cache_index].previous_pts_us = l->current_pts_us; |
| | 313 | |
| | 314 | if (s->cache_index + 1 >= s->cache_size / sizeof(*(s->cache))) { |
| | 315 | void *ptr = av_fast_realloc(s->cache, &s->cache_size, s->cache_size * 2); |
| | 316 | |
| | 317 | if (!ptr) |
| | 318 | return AVERROR(ENOMEM); |
| | 319 | s->cache = ptr; |
| | 320 | } |
| | 321 | s->cache_index++; |
| | 322 | |
| | 323 | return 0; |
| 261 | } | 324 | } |
| 262 | | 325 | |
| 263 | static int create_frame(AVFilterContext *ctx, int64_t pts) | 326 | static int create_frame(AVFilterContext *ctx, int64_t pts) |
| @@ -265,7 +328,7 @@ static int create_frame(AVFilterContext *ctx, int64_t pts) · 1 unmodified line |
| 265 | GraphMonitorContext *s = ctx->priv; | 328 | GraphMonitorContext *s = ctx->priv; |
| 266 | AVFilterLink *outlink = ctx->outputs[0]; | 329 | AVFilterLink *outlink = ctx->outputs[0]; |
| 267 | AVFrame *out; | 330 | AVFrame *out; |
| 268 | int xpos, ypos = 0; | 331 | int ret, xpos, ypos = 0; |
| 269 | | 332 | |
| 270 | out = ff_get_video_buffer(outlink, outlink->w, outlink->h); | 333 | out = ff_get_video_buffer(outlink, outlink->w, outlink->h); |
| 271 | if (!out) | 334 | if (!out) |
| @@ -273,6 +336,8 @@ static int create_frame(AVFilterContext *ctx, int64_t pts) · 1 unmodified line |
| 273 | | 336 | |
| 274 | clear_image(s, out, outlink); | 337 | clear_image(s, out, outlink); |
| 275 | | 338 | |
| | 339 | s->cache_index = 0; |
| | 340 | |
| 276 | for (int i = 0; i < ctx->graph->nb_filters; i++) { | 341 | for (int i = 0; i < ctx->graph->nb_filters; i++) { |
| 277 | AVFilterContext *filter = ctx->graph->filters[i]; | 342 | AVFilterContext *filter = ctx->graph->filters[i]; |
| 278 | char buffer[1024] = { 0 }; | 343 | char buffer[1024] = { 0 }; |
| @@ -298,7 +363,9 @@ static int create_frame(AVFilterContext *ctx, int64_t pts) · 19 unmodified lines |
| 298 | xpos += strlen(buffer) * 8; | 363 | xpos += strlen(buffer) * 8; |
| 299 | drawtext(out, xpos, ypos, l->src->name, s->white); | 364 | drawtext(out, xpos, ypos, l->src->name, s->white); |
| 300 | xpos += strlen(l->src->name) * 8 + 10; | 365 | xpos += strlen(l->src->name) * 8 + 10; |
| 301 | draw_items(ctx, out, xpos, ypos, l, frames); | 366 | ret = draw_items(ctx, out, xpos, ypos, l, frames); |
| | 367 | if (ret < 0) |
| | 368 | goto error; |
| 302 | ypos += 10; | 369 | ypos += 10; |
| 303 | } | 370 | } |
| 304 | | 371 | |
| @@ -316,7 +383,9 @@ static int create_frame(AVFilterContext *ctx, int64_t pts) · 11 unmodified lines |
| 316 | xpos += strlen(buffer) * 8; | 383 | xpos += strlen(buffer) * 8; |
| 317 | drawtext(out, xpos, ypos, l->dst->name, s->white); | 384 | drawtext(out, xpos, ypos, l->dst->name, s->white); |
| 318 | xpos += strlen(l->dst->name) * 8 + 10; | 385 | xpos += strlen(l->dst->name) * 8 + 10; |
| 319 | draw_items(ctx, out, xpos, ypos, l, frames); | 386 | ret = draw_items(ctx, out, xpos, ypos, l, frames); |
| | 387 | if (ret < 0) |
| | 388 | goto error; |
| 320 | ypos += 10; | 389 | ypos += 10; |
| 321 | } | 390 | } |
| 322 | ypos += 5; | 391 | ypos += 5; |
| @@ -325,6 +394,9 @@ static int create_frame(AVFilterContext *ctx, int64_t pts) · 2 unmodified lines |
| 325 | out->pts = pts; | 394 | out->pts = pts; |
| 326 | s->pts = pts + 1; | 395 | s->pts = pts + 1; |
| 327 | return ff_filter_frame(outlink, out); | 396 | return ff_filter_frame(outlink, out); |
| | 397 | error: |
| | 398 | av_frame_free(&out); |
| | 399 | return ret; |
| 328 | } | 400 | } |
| 329 | | 401 | |
| 330 | static int activate(AVFilterContext *ctx) | 402 | static int activate(AVFilterContext *ctx) |
| @@ -386,6 +458,14 @@ static int config_output(AVFilterLink *outlink) · 55 unmodified lines |
| 386 | return 0; | 458 | return 0; |
| 387 | } | 459 | } |
| 388 | | 460 | |
| | 461 | static av_cold void uninit(AVFilterContext *ctx) |
| | 462 | { |
| | 463 | GraphMonitorContext *s = ctx->priv; |
| | 464 | |
| | 465 | av_freep(&s->cache); |
| | 466 | s->cache_size = s->cache_index = 0; |
| | 467 | } |
| | 468 | |
| 389 | AVFILTER_DEFINE_CLASS_EXT(graphmonitor, "(a)graphmonitor", graphmonitor_options); | 469 | AVFILTER_DEFINE_CLASS_EXT(graphmonitor, "(a)graphmonitor", graphmonitor_options); |
| 390 | | 470 | |
| 391 | #if CONFIG_GRAPHMONITOR_FILTER | 471 | #if CONFIG_GRAPHMONITOR_FILTER |
| @@ -410,6 +490,8 @@ const AVFilter ff_vf_graphmonitor = { · 18 unmodified lines |
| 410 | .description = NULL_IF_CONFIG_SMALL("Show various filtergraph stats."), | 490 | .description = NULL_IF_CONFIG_SMALL("Show various filtergraph stats."), |
| 411 | .priv_size = sizeof(GraphMonitorContext), | 491 | .priv_size = sizeof(GraphMonitorContext), |
| 412 | .priv_class = &graphmonitor_class, | 492 | .priv_class = &graphmonitor_class, |
| | 493 | .init = init, |
| | 494 | .uninit = uninit, |
| 413 | .activate = activate, | 495 | .activate = activate, |
| 414 | FILTER_INPUTS(graphmonitor_inputs), | 496 | FILTER_INPUTS(graphmonitor_inputs), |
| 415 | FILTER_OUTPUTS(graphmonitor_outputs), | 497 | FILTER_OUTPUTS(graphmonitor_outputs), |
| @@ -440,6 +522,8 @@ const AVFilter ff_avf_agraphmonitor = { · 24 unmodified lines |
| 440 | .description = NULL_IF_CONFIG_SMALL("Show various filtergraph stats."), | 522 | .description = NULL_IF_CONFIG_SMALL("Show various filtergraph stats."), |
| 441 | .priv_class = &graphmonitor_class, | 523 | .priv_class = &graphmonitor_class, |
| 442 | .priv_size = sizeof(GraphMonitorContext), | 524 | .priv_size = sizeof(GraphMonitorContext), |
| | 525 | .init = init, |
| | 526 | .uninit = uninit, |
| 443 | .activate = activate, | 527 | .activate = activate, |
| 444 | FILTER_INPUTS(agraphmonitor_inputs), | 528 | FILTER_INPUTS(agraphmonitor_inputs), |
| 445 | FILTER_OUTPUTS(agraphmonitor_outputs), | 529 | FILTER_OUTPUTS(agraphmonitor_outputs), |