diff options
author | Paul B Mahol <onemda@gmail.com> | 2022-11-30 18:03:00 +0100 |
---|---|---|
committer | Paul B Mahol <onemda@gmail.com> | 2022-11-30 18:06:42 +0100 |
commit | 7d20635aeb4e6dc51549424d1999e44c86b38e11 (patch) | |
tree | eeae224d99ec0f59eb4bf904f6064292b5a40de4 | |
parent | bcb5ef667d202a55d903d075bfafe4ced93b7c96 (diff) | |
download | ffmpeg-7d20635aeb4e6dc51549424d1999e44c86b38e11.tar.gz |
avfilter/avf_showcwt: add frame slide mode
-rw-r--r-- | doc/filters.texi | 1 | ||||
-rw-r--r-- | libavfilter/avf_showcwt.c | 113 |
2 files changed, 99 insertions, 15 deletions
diff --git a/doc/filters.texi b/doc/filters.texi index c25d7aaecc..d64ce1734b 100644 --- a/doc/filters.texi +++ b/doc/filters.texi @@ -29353,6 +29353,7 @@ Set the output slide method. Allowed values are: @table @option @item replace @item scroll +@item frame @end table @item direction diff --git a/libavfilter/avf_showcwt.c b/libavfilter/avf_showcwt.c index db94a490bc..5e09ee5d04 100644 --- a/libavfilter/avf_showcwt.c +++ b/libavfilter/avf_showcwt.c @@ -54,6 +54,7 @@ enum DirectionMode { enum SlideMode { SLIDE_REPLACE, SLIDE_SCROLL, + SLIDE_FRAME, NB_SLIDE }; @@ -94,6 +95,7 @@ typedef struct ShowCWTContext { int pps; int eof; int slide; + int new_frame; int direction; int hop_size; int hop_index; @@ -138,6 +140,7 @@ static const AVOption showcwt_options[] = { { "slide", "set slide mode", OFFSET(slide), AV_OPT_TYPE_INT, {.i64=0}, 0, NB_SLIDE-1, FLAGS, "slide" }, { "replace", "replace", 0, AV_OPT_TYPE_CONST,{.i64=SLIDE_REPLACE},0, 0, FLAGS, "slide" }, { "scroll", "scroll", 0, AV_OPT_TYPE_CONST,{.i64=SLIDE_SCROLL}, 0, 0, FLAGS, "slide" }, + { "frame", "frame", 0, AV_OPT_TYPE_CONST,{.i64=SLIDE_FRAME}, 0, 0, FLAGS, "slide" }, { "direction", "set direction mode", OFFSET(direction), AV_OPT_TYPE_INT, {.i64=0}, 0, NB_DIRECTION-1, FLAGS, "direction" }, { "lr", "left to right", 0, AV_OPT_TYPE_CONST,{.i64=DIRECTION_LR}, 0, 0, FLAGS, "direction" }, { "rl", "right to left", 0, AV_OPT_TYPE_CONST,{.i64=DIRECTION_RL}, 0, 0, FLAGS, "direction" }, @@ -330,6 +333,7 @@ static int draw(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs) switch (s->slide) { case SLIDE_REPLACE: + case SLIDE_FRAME: /* nothing to do here */ break; case SLIDE_SCROLL: @@ -515,6 +519,7 @@ static int config_output(AVFilterLink *outlink) break; } + s->new_frame = 1; s->nb_threads = FFMIN(s->frequency_band_count, ff_filter_get_nb_threads(ctx)); s->nb_channels = inlink->ch_layout.nb_channels; s->old_pts = AV_NOPTS_VALUE; @@ -675,7 +680,6 @@ static int output_frame(AVFilterContext *ctx) AVFilterLink *outlink = ctx->outputs[0]; AVFilterLink *inlink = ctx->inputs[0]; ShowCWTContext *s = ctx->priv; - int64_t pts_offset; int ret; switch (s->slide) { @@ -709,35 +713,37 @@ static int output_frame(AVFilterContext *ctx) ff_filter_execute(ctx, draw, NULL, NULL, s->nb_threads); - pts_offset = av_rescale(s->ihop_index, s->hop_size, s->ihop_size); - s->outpicref->pts = av_rescale_q(s->in_pts + pts_offset, inlink->time_base, outlink->time_base); - - s->ihop_index++; - if (s->ihop_index >= s->ihop_size) - s->ihop_index = 0; - switch (s->slide) { case SLIDE_REPLACE: + case SLIDE_FRAME: switch (s->direction) { case DIRECTION_LR: s->pos++; - if (s->pos >= s->w) + if (s->pos >= s->w) { s->pos = 0; + s->new_frame = 1; + } break; case DIRECTION_RL: s->pos--; - if (s->pos < 0) + if (s->pos < 0) { s->pos = s->w - 1; + s->new_frame = 1; + } break; case DIRECTION_UD: s->pos++; - if (s->pos >= s->h) + if (s->pos >= s->h) { s->pos = 0; + s->new_frame = 1; + } break; case DIRECTION_DU: s->pos--; - if (s->pos < 0) + if (s->pos < 0) { s->pos = s->h - 1; + s->new_frame = 1; + } break; } break; @@ -757,6 +763,77 @@ static int output_frame(AVFilterContext *ctx) break; } + if (s->slide == SLIDE_FRAME && s->eof) { + switch (s->direction) { + case DIRECTION_LR: + for (int p = 0; p < 3; p++) { + ptrdiff_t linesize = s->outpicref->linesize[p]; + const int size = s->w - s->pos; + const int fill = p ? 128 : 0; + const int x = s->pos; + + for (int y = 0; y < s->h; y++) { + uint8_t *dst = s->outpicref->data[p] + y * linesize + x; + + memset(dst, fill, size); + } + } + break; + case DIRECTION_RL: + for (int p = 0; p < 3; p++) { + ptrdiff_t linesize = s->outpicref->linesize[p]; + const int size = s->w - s->pos; + const int fill = p ? 128 : 0; + + for (int y = 0; y < s->h; y++) { + uint8_t *dst = s->outpicref->data[p] + y * linesize; + + memset(dst, fill, size); + } + } + break; + case DIRECTION_UD: + for (int p = 0; p < 3; p++) { + ptrdiff_t linesize = s->outpicref->linesize[p]; + const int fill = p ? 128 : 0; + + for (int y = s->pos; y < s->h; y++) { + uint8_t *dst = s->outpicref->data[p] + y * linesize; + + memset(dst, fill, s->w); + } + } + break; + case DIRECTION_DU: + for (int p = 0; p < 3; p++) { + ptrdiff_t linesize = s->outpicref->linesize[p]; + const int fill = p ? 128 : 0; + + for (int y = s->h - s->pos; y >= 0; y--) { + uint8_t *dst = s->outpicref->data[p] + y * linesize; + + memset(dst, fill, s->w); + } + } + break; + } + } + + s->new_frame = s->slide == SLIDE_FRAME && (s->new_frame || s->eof); + + if (s->slide != SLIDE_FRAME || s->new_frame == 1) { + int64_t pts_offset = s->new_frame ? 0LL : av_rescale(s->ihop_index, s->hop_size, s->ihop_size); + + s->outpicref->pts = av_rescale_q(s->in_pts + pts_offset, inlink->time_base, outlink->time_base); + } + + s->ihop_index++; + if (s->ihop_index >= s->ihop_size) + s->ihop_index = 0; + + if (s->slide == SLIDE_FRAME && s->new_frame == 0) + return 1; + if (s->old_pts < s->outpicref->pts) { AVFrame *out = ff_get_video_buffer(outlink, outlink->w, outlink->h); if (!out) @@ -768,6 +845,7 @@ static int output_frame(AVFilterContext *ctx) if (ret < 0) goto fail; s->old_pts = s->outpicref->pts; + s->new_frame = 0; ret = ff_filter_frame(outlink, out); if (ret <= 0) return ret; @@ -816,8 +894,10 @@ static int activate(AVFilterContext *ctx) ff_filter_execute(ctx, run_channels_cwt_prepare, fin, NULL, FFMIN(s->nb_threads, s->nb_channels)); if (fin) { - if (s->hop_index == 0) + if ((s->hop_index == 0 && s->slide != SLIDE_FRAME) || s->new_frame) { s->in_pts = fin->pts; + s->new_frame = 0; + } s->hop_index += fin->nb_samples; av_frame_free(&fin); } else { @@ -843,9 +923,12 @@ static int activate(AVFilterContext *ctx) } } - if (s->eof && s->eof_pts != AV_NOPTS_VALUE && s->old_pts + 1 >= s->eof_pts) { + if (s->eof && s->eof_pts != AV_NOPTS_VALUE && + (s->old_pts + 1 >= s->eof_pts || (s->slide == SLIDE_FRAME))) { + if (s->slide == SLIDE_FRAME) + ret = output_frame(ctx); ff_outlink_set_status(outlink, AVERROR_EOF, s->eof_pts); - return 0; + return ret; } if (!s->eof && ff_inlink_acknowledge_status(inlink, &status, &pts)) { |