History

avfilter/avf_showwaves: force output to fixed framerate if rate is set

Paul B Mahol committed 3 years ago

Commit ee664f41 parent c4cdd791 file · +100 −61Browse files

Unified · Split

libavfilter/avf_showwaves.c+100−61
@@ -77,10 +77,12 @@ typedef struct ShowWavesContext { · 76 unmodified lines
77 char *colors;77 char *colors;
78 int buf_idx;78 int buf_idx;
79 int16_t *buf_idy; /* y coordinate of previous sample for each channel */79 int16_t *buf_idy; /* y coordinate of previous sample for each channel */
80 int16_t *history;
81 int history_nb_samples;
82 int history_index;
80 AVFrame *outpicref;83 AVFrame *outpicref;
81 int n;84 AVRational n, q, c;
82 int pixstep;85 int pixstep;
83 int sample_count_mod;
84 int mode; ///< ShowWavesMode86 int mode; ///< ShowWavesMode
85 int scale; ///< ShowWavesScale87 int scale; ///< ShowWavesScale
86 int draw_mode; ///< ShowWavesDrawMode88 int draw_mode; ///< ShowWavesDrawMode
@@ -111,7 +113,7 @@ static const AVOption showwaves_options[] = { · 24 unmodified lines
111 { "line", "draw a line for each sample", 0, AV_OPT_TYPE_CONST, {.i64=MODE_LINE}, .flags=FLAGS, .unit="mode"},113 { "line", "draw a line for each sample", 0, AV_OPT_TYPE_CONST, {.i64=MODE_LINE}, .flags=FLAGS, .unit="mode"},
112 { "p2p", "draw a line between samples", 0, AV_OPT_TYPE_CONST, {.i64=MODE_P2P}, .flags=FLAGS, .unit="mode"},114 { "p2p", "draw a line between samples", 0, AV_OPT_TYPE_CONST, {.i64=MODE_P2P}, .flags=FLAGS, .unit="mode"},
113 { "cline", "draw a centered line for each sample", 0, AV_OPT_TYPE_CONST, {.i64=MODE_CENTERED_LINE}, .flags=FLAGS, .unit="mode"},115 { "cline", "draw a centered line for each sample", 0, AV_OPT_TYPE_CONST, {.i64=MODE_CENTERED_LINE}, .flags=FLAGS, .unit="mode"},
114 { "n", "set how many samples to show in the same point", OFFSET(n), AV_OPT_TYPE_INT, {.i64 = 0}, 0, INT_MAX, FLAGS },116 { "n", "set how many samples to show in the same point", OFFSET(n), AV_OPT_TYPE_RATIONAL, {.i64 = 0}, 0, INT_MAX, FLAGS },
115 { "rate", "set video rate", OFFSET(rate), AV_OPT_TYPE_VIDEO_RATE, {.str = "25"}, 0, INT_MAX, FLAGS },117 { "rate", "set video rate", OFFSET(rate), AV_OPT_TYPE_VIDEO_RATE, {.str = "25"}, 0, INT_MAX, FLAGS },
116 { "r", "set video rate", OFFSET(rate), AV_OPT_TYPE_VIDEO_RATE, {.str = "25"}, 0, INT_MAX, FLAGS },118 { "r", "set video rate", OFFSET(rate), AV_OPT_TYPE_VIDEO_RATE, {.str = "25"}, 0, INT_MAX, FLAGS },
117 { "split_channels", "draw channels separately", OFFSET(split_channels), AV_OPT_TYPE_BOOL, {.i64 = 0}, 0, 1, FLAGS },119 { "split_channels", "draw channels separately", OFFSET(split_channels), AV_OPT_TYPE_BOOL, {.i64 = 0}, 0, 1, FLAGS },
@@ -135,6 +137,7 @@ static av_cold void uninit(AVFilterContext *ctx) · 17 unmodified lines
135 137
136 av_frame_free(&showwaves->outpicref);138 av_frame_free(&showwaves->outpicref);
137 av_freep(&showwaves->buf_idy);139 av_freep(&showwaves->buf_idy);
140 av_freep(&showwaves->history);
138 av_freep(&showwaves->fg);141 av_freep(&showwaves->fg);
139 142
140 if (showwaves->single_pic) {143 if (showwaves->single_pic) {
@@ -422,29 +425,42 @@ static int config_output(AVFilterLink *outlink) · 281 unmodified lines
422 uint8_t x;425 uint8_t x;
423 int ch;426 int ch;
424 427
425 if (showwaves->single_pic)428 showwaves->q = av_make_q(0, 1);
426 showwaves->n = 1;429 showwaves->c = av_make_q(0, 1);
427 430
428 if (!showwaves->n)431 if (showwaves->single_pic) {
429 showwaves->n = FFMAX(1, av_rescale_q(inlink->sample_rate, av_make_q(1, showwaves->w), showwaves->rate));432 showwaves->n = av_make_q(1, 1);
433 outlink->frame_rate = av_make_q(1, 1);
434 } else {
435 if (!showwaves->n.num || !showwaves->n.den) {
436 showwaves->n = av_mul_q(av_make_q(inlink->sample_rate,
437 showwaves->w), av_inv_q(showwaves->rate));
438 outlink->frame_rate = showwaves->rate;
439 } else {
440 outlink->frame_rate = av_div_q(av_make_q(inlink->sample_rate, showwaves->w), showwaves->n);
441 }
442 }
430 443
431 showwaves->buf_idx = 0;444 showwaves->buf_idx = 0;
432 if (!FF_ALLOCZ_TYPED_ARRAY(showwaves->buf_idy, nb_channels)) {445 if (!FF_ALLOCZ_TYPED_ARRAY(showwaves->buf_idy, nb_channels)) {
433 av_log(ctx, AV_LOG_ERROR, "Could not allocate showwaves buffer\n");446 av_log(ctx, AV_LOG_ERROR, "Could not allocate showwaves buffer\n");
434 return AVERROR(ENOMEM);447 return AVERROR(ENOMEM);
435 }448 }
449
450 showwaves->history_nb_samples = av_rescale(showwaves->w * nb_channels * 2,
451 showwaves->n.num, showwaves->n.den);
452 showwaves->history = av_calloc(showwaves->history_nb_samples,
453 sizeof(*showwaves->history));
454 if (!showwaves->history)
455 return AVERROR(ENOMEM);
456
457 outlink->time_base = av_inv_q(outlink->frame_rate);
436 outlink->w = showwaves->w;458 outlink->w = showwaves->w;
437 outlink->h = showwaves->h;459 outlink->h = showwaves->h;
438 outlink->sample_aspect_ratio = (AVRational){1,1};460 outlink->sample_aspect_ratio = (AVRational){1,1};
439 461
440 if (showwaves->single_pic)462 av_log(ctx, AV_LOG_VERBOSE, "s:%dx%d r:%f n:%f\n",
441 outlink->frame_rate = av_make_q(1, 1);463 showwaves->w, showwaves->h, av_q2d(outlink->frame_rate), av_q2d(showwaves->n));
442 else
443 outlink->frame_rate = av_div_q((AVRational){inlink->sample_rate,showwaves->n},
444 (AVRational){showwaves->w,1});
445
446 av_log(ctx, AV_LOG_VERBOSE, "s:%dx%d r:%f n:%d\n",
447 showwaves->w, showwaves->h, av_q2d(outlink->frame_rate), showwaves->n);
448 464
449 switch (outlink->format) {465 switch (outlink->format) {
450 case AV_PIX_FMT_GRAY8:466 case AV_PIX_FMT_GRAY8:
@@ -524,7 +540,7 @@ static int config_output(AVFilterLink *outlink) · 73 unmodified lines
524 540
525 if (showwaves->draw_mode == DRAW_SCALE) {541 if (showwaves->draw_mode == DRAW_SCALE) {
526 /* multiplication factor, pre-computed to avoid in-loop divisions */542 /* multiplication factor, pre-computed to avoid in-loop divisions */
527 x = 255 / ((showwaves->split_channels ? 1 : nb_channels) * showwaves->n);543 x = (showwaves->n.den * 255) / ((showwaves->split_channels ? 1 : nb_channels) * showwaves->n.num);
528 } else {544 } else {
529 x = 255;545 x = 255;
530 }546 }
@@ -551,18 +567,23 @@ static int config_output(AVFilterLink *outlink) · 20 unmodified lines
551 return 0;567 return 0;
552}568}
553 569
554inline static int push_frame(AVFilterLink *outlink)570inline static int push_frame(AVFilterLink *outlink, int i, int64_t pts)
555{571{
556 AVFilterContext *ctx = outlink->src;572 AVFilterContext *ctx = outlink->src;
557 AVFilterLink *inlink = ctx->inputs[0];573 AVFilterLink *inlink = ctx->inputs[0];
558 ShowWavesContext *showwaves = outlink->src->priv;574 ShowWavesContext *showwaves = outlink->src->priv;
559 int nb_channels = inlink->ch_layout.nb_channels;575 int nb_channels = inlink->ch_layout.nb_channels;
560 int ret, i;576 int ret;
577
578 showwaves->outpicref->duration = 1;
579 showwaves->outpicref->pts = av_rescale_q(pts + i,
580 inlink->time_base,
581 outlink->time_base);
561 582
562 ret = ff_filter_frame(outlink, showwaves->outpicref);583 ret = ff_filter_frame(outlink, showwaves->outpicref);
563 showwaves->outpicref = NULL;584 showwaves->outpicref = NULL;
564 showwaves->buf_idx = 0;585 showwaves->buf_idx = 0;
565 for (i = 0; i < nb_channels; i++)586 for (int i = 0; i < nb_channels; i++)
566 showwaves->buf_idy[i] = 0;587 showwaves->buf_idy[i] = 0;
567 return ret;588 return ret;
568}589}
@@ -633,7 +654,7 @@ static int push_single_pic(AVFilterLink *outlink) · 64 unmodified lines
633 }654 }
634 }655 }
635 656
636 return push_frame(outlink);657 return push_frame(outlink, 0, 0);
637}658}
638 659
639 660
@@ -645,31 +666,23 @@ static int request_frame(AVFilterLink *outlink) · 5 unmodified lines
645 666
646 ret = ff_request_frame(inlink);667 ret = ff_request_frame(inlink);
647 if (ret == AVERROR_EOF && showwaves->outpicref) {668 if (ret == AVERROR_EOF && showwaves->outpicref) {
648 if (showwaves->single_pic)669 push_single_pic(outlink);
649 push_single_pic(outlink);
650 else
651 push_frame(outlink);
652 }670 }
653 671
654 return ret;672 return ret;
655}673}
656 674
657static int alloc_out_frame(ShowWavesContext *showwaves, const int16_t *p,675static int alloc_out_frame(ShowWavesContext *showwaves,
658 const AVFilterLink *inlink, AVFilterLink *outlink,676 AVFilterLink *outlink)
659 const AVFrame *in)
660{677{
661 if (!showwaves->outpicref) {678 if (!showwaves->outpicref) {
662 int j;
663 AVFrame *out = showwaves->outpicref =679 AVFrame *out = showwaves->outpicref =
664 ff_get_video_buffer(outlink, outlink->w, outlink->h);680 ff_get_video_buffer(outlink, outlink->w, outlink->h);
665 if (!out)681 if (!out)
666 return AVERROR(ENOMEM);682 return AVERROR(ENOMEM);
667 out->width = outlink->w;683 out->width = outlink->w;
668 out->height = outlink->h;684 out->height = outlink->h;
669 out->pts = in->pts + av_rescale_q((p - (int16_t *)in->data[0]) / inlink->ch_layout.nb_channels,685 for (int j = 0; j < outlink->h; j++)
670 av_make_q(1, inlink->sample_rate),
671 outlink->time_base);
672 for (j = 0; j < outlink->h; j++)
673 memset(out->data[0] + j*out->linesize[0], 0, outlink->w * showwaves->pixstep);686 memset(out->data[0] + j*out->linesize[0], 0, outlink->w * showwaves->pixstep);
674 }687 }
675 return 0;688 return 0;
@@ -696,45 +709,67 @@ static int showwaves_filter_frame(AVFilterLink *inlink, AVFrame *insamples) · 20 unmodified lines
696 ShowWavesContext *showwaves = ctx->priv;709 ShowWavesContext *showwaves = ctx->priv;
697 const int nb_samples = insamples->nb_samples;710 const int nb_samples = insamples->nb_samples;
698 AVFrame *outpicref = showwaves->outpicref;711 AVFrame *outpicref = showwaves->outpicref;
699 int16_t *p = (int16_t *)insamples->data[0];712 const int16_t *p = (const int16_t *)insamples->data[0];
700 int nb_channels = inlink->ch_layout.nb_channels;713 int16_t *history = showwaves->history;
701 int i, j, ret = 0;714 const int nb_channels = inlink->ch_layout.nb_channels;
715 int i, j, ret = 0, linesize;
702 const int pixstep = showwaves->pixstep;716 const int pixstep = showwaves->pixstep;
703 const int n = showwaves->n;
704 const int ch_height = showwaves->split_channels ? outlink->h / nb_channels : outlink->h;717 const int ch_height = showwaves->split_channels ? outlink->h / nb_channels : outlink->h;
718 const int history_nb_samples = showwaves->history_nb_samples;
719 const int split_channels = showwaves->split_channels;
720 const AVRational i_n = av_inv_q(showwaves->n);
721 const AVRational u_q = av_make_q(1, 1);
722 const AVRational z_q = av_make_q(0, 1);
723 int16_t *buf_idy = showwaves->buf_idy;
724 int idx = showwaves->history_index;
725 int buf_idx = showwaves->buf_idx;
726 const uint8_t *fg = showwaves->fg;
727 const int w = showwaves->w;
728 uint8_t *dst;
729
730 for (int n = 0; n < nb_samples * nb_channels; n++) {
731 history[idx++] = p[n];
732 if (idx >= history_nb_samples)
733 idx = 0;
734 }
735 showwaves->history_index = idx;
705 736
706 /* draw data in the buffer */737 ret = alloc_out_frame(showwaves, outlink);
707 for (i = 0; i < nb_samples; i++) {738 if (ret < 0)
708 739 goto end;
709 ret = alloc_out_frame(showwaves, p, inlink, outlink, insamples);740 outpicref = showwaves->outpicref;
710 if (ret < 0)741 linesize = outpicref->linesize[0];
711 goto end;
712 outpicref = showwaves->outpicref;
713 742
743 /* draw data in the buffer */
744 dst = outpicref->data[0];
745 for (i = 0; i < history_nb_samples; i++) {
714 for (j = 0; j < nb_channels; j++) {746 for (j = 0; j < nb_channels; j++) {
715 uint8_t *buf = outpicref->data[0] + showwaves->buf_idx * pixstep;747 uint8_t *buf = dst + buf_idx * pixstep;
716 const int linesize = outpicref->linesize[0];
717 int h;748 int h;
718 749
719 if (showwaves->split_channels)750 if (split_channels)
720 buf += j*ch_height*linesize;751 buf += j*ch_height*linesize;
721 h = showwaves->get_h(*p++, ch_height);752 h = showwaves->get_h(history[idx++], ch_height);
753 if (idx >= history_nb_samples)
754 idx = 0;
722 showwaves->draw_sample(buf, ch_height, linesize,755 showwaves->draw_sample(buf, ch_height, linesize,
723 &showwaves->buf_idy[j], &showwaves->fg[j * 4], h);756 &buf_idy[j], &fg[j * 4], h);
724 }757 }
725 758
726 showwaves->sample_count_mod++;759 showwaves->c = av_add_q(showwaves->c, i_n);
727 if (showwaves->sample_count_mod == n) {760 if (av_cmp_q(showwaves->c, u_q) >= 0) {
728 showwaves->sample_count_mod = 0;761 showwaves->c = z_q;
729 showwaves->buf_idx++;762 buf_idx++;
730 }763 }
731 if (showwaves->buf_idx == showwaves->w ||764 if (buf_idx == w)
732 (ff_outlink_get_status(inlink) && i == nb_samples - 1))765 break;
733 if ((ret = push_frame(outlink)) < 0)
734 break;
735 outpicref = showwaves->outpicref;
736 }766 }
737 767
768 showwaves->buf_idx = buf_idx;
769
770 if ((ret = push_frame(outlink, history_nb_samples - i - 1, insamples->pts)) < 0)
771 goto end;
772 outpicref = showwaves->outpicref;
738end:773end:
739 av_frame_free(&insamples);774 av_frame_free(&insamples);
740 return ret;775 return ret;
@@ -745,17 +780,22 @@ static int activate(AVFilterContext *ctx) · 4 unmodified lines
745 AVFilterLink *inlink = ctx->inputs[0];780 AVFilterLink *inlink = ctx->inputs[0];
746 AVFilterLink *outlink = ctx->outputs[0];781 AVFilterLink *outlink = ctx->outputs[0];
747 ShowWavesContext *showwaves = ctx->priv;782 ShowWavesContext *showwaves = ctx->priv;
783 AVRational q;
748 AVFrame *in;784 AVFrame *in;
749 const int nb_samples = showwaves->n * outlink->w;785 int nb_samples;
750 int ret;786 int ret;
751 787
752 FF_FILTER_FORWARD_STATUS_BACK(outlink, inlink);788 FF_FILTER_FORWARD_STATUS_BACK(outlink, inlink);
753 789
790 q = av_add_q(showwaves->q, av_mul_q(av_make_q(outlink->w, 1), showwaves->n));
791 nb_samples = (q.num + (q.den / 2)) / q.den;
754 ret = ff_inlink_consume_samples(inlink, nb_samples, nb_samples, &in);792 ret = ff_inlink_consume_samples(inlink, nb_samples, nb_samples, &in);
755 if (ret < 0)793 if (ret < 0)
756 return ret;794 return ret;
757 if (ret > 0)795 if (ret > 0) {
796 showwaves->q = av_sub_q(q, av_make_q(nb_samples, 1));
758 return showwaves_filter_frame(inlink, in);797 return showwaves_filter_frame(inlink, in);
798 }
759 799
760 FF_FILTER_FORWARD_STATUS(inlink, outlink);800 FF_FILTER_FORWARD_STATUS(inlink, outlink);
761 FF_FILTER_FORWARD_WANTED(outlink, inlink);801 FF_FILTER_FORWARD_WANTED(outlink, inlink);
@@ -838,13 +878,12 @@ static int showwavespic_filter_frame(AVFilterLink *inlink, AVFrame *insamples) · 76 unmodified lines
838 AVFilterContext *ctx = inlink->dst;878 AVFilterContext *ctx = inlink->dst;
839 AVFilterLink *outlink = ctx->outputs[0];879 AVFilterLink *outlink = ctx->outputs[0];
840 ShowWavesContext *showwaves = ctx->priv;880 ShowWavesContext *showwaves = ctx->priv;
841 int16_t *p = (int16_t *)insamples->data[0];
842 int ret = 0;881 int ret = 0;
843 882
844 if (showwaves->single_pic) {883 if (showwaves->single_pic) {
845 struct frame_node *f;884 struct frame_node *f;
846 885
847 ret = alloc_out_frame(showwaves, p, inlink, outlink, insamples);886 ret = alloc_out_frame(showwaves, outlink);
848 if (ret < 0)887 if (ret < 0)
849 goto end;888 goto end;
850 889

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t