Showing the changes to libavfilter (1 of 1 file). Show all
Unified · Split
| @@ -77,10 +77,12 @@ typedef struct ShowWavesContext { · 76 unmodified lines | ||
| 77 | 77 | char *colors; |
| 78 | 78 | int buf_idx; |
| 79 | 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 | 83 | AVFrame *outpicref; |
| 81 | − int n; | |
| 84 | + AVRational n, q, c; | |
| 82 | 85 | int pixstep; |
| 83 | − int sample_count_mod; | |
| 84 | 86 | int mode; ///< ShowWavesMode |
| 85 | 87 | int scale; ///< ShowWavesScale |
| 86 | 88 | int draw_mode; ///< ShowWavesDrawMode |
| @@ -111,7 +113,7 @@ static const AVOption showwaves_options[] = { · 24 unmodified lines | ||
| 111 | 113 | { "line", "draw a line for each sample", 0, AV_OPT_TYPE_CONST, {.i64=MODE_LINE}, .flags=FLAGS, .unit="mode"}, |
| 112 | 114 | { "p2p", "draw a line between samples", 0, AV_OPT_TYPE_CONST, {.i64=MODE_P2P}, .flags=FLAGS, .unit="mode"}, |
| 113 | 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 | 117 | { "rate", "set video rate", OFFSET(rate), AV_OPT_TYPE_VIDEO_RATE, {.str = "25"}, 0, INT_MAX, FLAGS }, |
| 116 | 118 | { "r", "set video rate", OFFSET(rate), AV_OPT_TYPE_VIDEO_RATE, {.str = "25"}, 0, INT_MAX, FLAGS }, |
| 117 | 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 | 138 | av_frame_free(&showwaves->outpicref); |
| 137 | 139 | av_freep(&showwaves->buf_idy); |
| 140 | + av_freep(&showwaves->history); | |
| 138 | 141 | av_freep(&showwaves->fg); |
| 139 | 142 | |
| 140 | 143 | if (showwaves->single_pic) { |
| @@ -422,29 +425,42 @@ static int config_output(AVFilterLink *outlink) · 281 unmodified lines | ||
| 422 | 425 | uint8_t x; |
| 423 | 426 | int ch; |
| 424 | 427 | |
| 425 | − if (showwaves->single_pic) | |
| 426 | − showwaves->n = 1; | |
| 428 | + showwaves->q = av_make_q(0, 1); | |
| 429 | + showwaves->c = av_make_q(0, 1); | |
| 427 | 430 | |
| 428 | − if (!showwaves->n) | |
| 429 | − showwaves->n = FFMAX(1, av_rescale_q(inlink->sample_rate, av_make_q(1, showwaves->w), showwaves->rate)); | |
| 431 | + if (showwaves->single_pic) { | |
| 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 | 444 | showwaves->buf_idx = 0; |
| 432 | 445 | if (!FF_ALLOCZ_TYPED_ARRAY(showwaves->buf_idy, nb_channels)) { |
| 433 | 446 | av_log(ctx, AV_LOG_ERROR, "Could not allocate showwaves buffer\n"); |
| 434 | 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 | 458 | outlink->w = showwaves->w; |
| 437 | 459 | outlink->h = showwaves->h; |
| 438 | 460 | outlink->sample_aspect_ratio = (AVRational){1,1}; |
| 439 | 461 | |
| 440 | − if (showwaves->single_pic) | |
| 441 | − outlink->frame_rate = av_make_q(1, 1); | |
| 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); | |
| 462 | + av_log(ctx, AV_LOG_VERBOSE, "s:%dx%d r:%f n:%f\n", | |
| 463 | + showwaves->w, showwaves->h, av_q2d(outlink->frame_rate), av_q2d(showwaves->n)); | |
| 448 | 464 | |
| 449 | 465 | switch (outlink->format) { |
| 450 | 466 | case AV_PIX_FMT_GRAY8: |
| @@ -524,7 +540,7 @@ static int config_output(AVFilterLink *outlink) · 73 unmodified lines | ||
| 524 | 540 | |
| 525 | 541 | if (showwaves->draw_mode == DRAW_SCALE) { |
| 526 | 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 | 544 | } else { |
| 529 | 545 | x = 255; |
| 530 | 546 | } |
| @@ -551,18 +567,23 @@ static int config_output(AVFilterLink *outlink) · 20 unmodified lines | ||
| 551 | 567 | return 0; |
| 552 | 568 | } |
| 553 | 569 | |
| 554 | −inline static int push_frame(AVFilterLink *outlink) | |
| 570 | +inline static int push_frame(AVFilterLink *outlink, int i, int64_t pts) | |
| 555 | 571 | { |
| 556 | 572 | AVFilterContext *ctx = outlink->src; |
| 557 | 573 | AVFilterLink *inlink = ctx->inputs[0]; |
| 558 | 574 | ShowWavesContext *showwaves = outlink->src->priv; |
| 559 | 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 | 583 | ret = ff_filter_frame(outlink, showwaves->outpicref); |
| 563 | 584 | showwaves->outpicref = NULL; |
| 564 | 585 | showwaves->buf_idx = 0; |
| 565 | − for (i = 0; i < nb_channels; i++) | |
| 586 | + for (int i = 0; i < nb_channels; i++) | |
| 566 | 587 | showwaves->buf_idy[i] = 0; |
| 567 | 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 | 667 | ret = ff_request_frame(inlink); |
| 647 | 668 | if (ret == AVERROR_EOF && showwaves->outpicref) { |
| 648 | − if (showwaves->single_pic) | |
| 649 | − push_single_pic(outlink); | |
| 650 | − else | |
| 651 | − push_frame(outlink); | |
| 669 | + push_single_pic(outlink); | |
| 652 | 670 | } |
| 653 | 671 | |
| 654 | 672 | return ret; |
| 655 | 673 | } |
| 656 | 674 | |
| 657 | −static int alloc_out_frame(ShowWavesContext *showwaves, const int16_t *p, | |
| 658 | − const AVFilterLink *inlink, AVFilterLink *outlink, | |
| 659 | − const AVFrame *in) | |
| 675 | +static int alloc_out_frame(ShowWavesContext *showwaves, | |
| 676 | + AVFilterLink *outlink) | |
| 660 | 677 | { |
| 661 | 678 | if (!showwaves->outpicref) { |
| 662 | − int j; | |
| 663 | 679 | AVFrame *out = showwaves->outpicref = |
| 664 | 680 | ff_get_video_buffer(outlink, outlink->w, outlink->h); |
| 665 | 681 | if (!out) |
| 666 | 682 | return AVERROR(ENOMEM); |
| 667 | 683 | out->width = outlink->w; |
| 668 | 684 | out->height = outlink->h; |
| 669 | − out->pts = in->pts + av_rescale_q((p - (int16_t *)in->data[0]) / inlink->ch_layout.nb_channels, | |
| 670 | − av_make_q(1, inlink->sample_rate), | |
| 671 | − outlink->time_base); | |
| 672 | − for (j = 0; j < outlink->h; j++) | |
| 685 | + for (int j = 0; j < outlink->h; j++) | |
| 673 | 686 | memset(out->data[0] + j*out->linesize[0], 0, outlink->w * showwaves->pixstep); |
| 674 | 687 | } |
| 675 | 688 | return 0; |
| @@ -696,45 +709,67 @@ static int showwaves_filter_frame(AVFilterLink *inlink, AVFrame *insamples) · 20 unmodified lines | ||
| 696 | 709 | ShowWavesContext *showwaves = ctx->priv; |
| 697 | 710 | const int nb_samples = insamples->nb_samples; |
| 698 | 711 | AVFrame *outpicref = showwaves->outpicref; |
| 699 | − int16_t *p = (int16_t *)insamples->data[0]; | |
| 700 | − int nb_channels = inlink->ch_layout.nb_channels; | |
| 701 | − int i, j, ret = 0; | |
| 712 | + const int16_t *p = (const int16_t *)insamples->data[0]; | |
| 713 | + int16_t *history = showwaves->history; | |
| 714 | + const int nb_channels = inlink->ch_layout.nb_channels; | |
| 715 | + int i, j, ret = 0, linesize; | |
| 702 | 716 | const int pixstep = showwaves->pixstep; |
| 703 | − const int n = showwaves->n; | |
| 704 | 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 */ | |
| 707 | − for (i = 0; i < nb_samples; i++) { | |
| 708 | − | |
| 709 | − ret = alloc_out_frame(showwaves, p, inlink, outlink, insamples); | |
| 710 | − if (ret < 0) | |
| 711 | − goto end; | |
| 712 | − outpicref = showwaves->outpicref; | |
| 737 | + ret = alloc_out_frame(showwaves, outlink); | |
| 738 | + if (ret < 0) | |
| 739 | + goto end; | |
| 740 | + outpicref = showwaves->outpicref; | |
| 741 | + linesize = outpicref->linesize[0]; | |
| 713 | 742 | |
| 743 | + /* draw data in the buffer */ | |
| 744 | + dst = outpicref->data[0]; | |
| 745 | + for (i = 0; i < history_nb_samples; i++) { | |
| 714 | 746 | for (j = 0; j < nb_channels; j++) { |
| 715 | − uint8_t *buf = outpicref->data[0] + showwaves->buf_idx * pixstep; | |
| 716 | − const int linesize = outpicref->linesize[0]; | |
| 747 | + uint8_t *buf = dst + buf_idx * pixstep; | |
| 717 | 748 | int h; |
| 718 | 749 | |
| 719 | − if (showwaves->split_channels) | |
| 750 | + if (split_channels) | |
| 720 | 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 | 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++; | |
| 727 | − if (showwaves->sample_count_mod == n) { | |
| 728 | − showwaves->sample_count_mod = 0; | |
| 729 | − showwaves->buf_idx++; | |
| 759 | + showwaves->c = av_add_q(showwaves->c, i_n); | |
| 760 | + if (av_cmp_q(showwaves->c, u_q) >= 0) { | |
| 761 | + showwaves->c = z_q; | |
| 762 | + buf_idx++; | |
| 730 | 763 | } |
| 731 | − if (showwaves->buf_idx == showwaves->w || | |
| 732 | − (ff_outlink_get_status(inlink) && i == nb_samples - 1)) | |
| 733 | − if ((ret = push_frame(outlink)) < 0) | |
| 734 | − break; | |
| 735 | − outpicref = showwaves->outpicref; | |
| 764 | + if (buf_idx == w) | |
| 765 | + break; | |
| 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; | |
| 738 | 773 | end: |
| 739 | 774 | av_frame_free(&insamples); |
| 740 | 775 | return ret; |
| @@ -745,17 +780,22 @@ static int activate(AVFilterContext *ctx) · 4 unmodified lines | ||
| 745 | 780 | AVFilterLink *inlink = ctx->inputs[0]; |
| 746 | 781 | AVFilterLink *outlink = ctx->outputs[0]; |
| 747 | 782 | ShowWavesContext *showwaves = ctx->priv; |
| 783 | + AVRational q; | |
| 748 | 784 | AVFrame *in; |
| 749 | − const int nb_samples = showwaves->n * outlink->w; | |
| 785 | + int nb_samples; | |
| 750 | 786 | int ret; |
| 751 | 787 | |
| 752 | 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 | 792 | ret = ff_inlink_consume_samples(inlink, nb_samples, nb_samples, &in); |
| 755 | 793 | if (ret < 0) |
| 756 | 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 | 797 | return showwaves_filter_frame(inlink, in); |
| 798 | + } | |
| 759 | 799 | |
| 760 | 800 | FF_FILTER_FORWARD_STATUS(inlink, outlink); |
| 761 | 801 | FF_FILTER_FORWARD_WANTED(outlink, inlink); |
| @@ -838,13 +878,12 @@ static int showwavespic_filter_frame(AVFilterLink *inlink, AVFrame *insamples) · 76 unmodified lines | ||
| 838 | 878 | AVFilterContext *ctx = inlink->dst; |
| 839 | 879 | AVFilterLink *outlink = ctx->outputs[0]; |
| 840 | 880 | ShowWavesContext *showwaves = ctx->priv; |
| 841 | − int16_t *p = (int16_t *)insamples->data[0]; | |
| 842 | 881 | int ret = 0; |
| 843 | 882 | |
| 844 | 883 | if (showwaves->single_pic) { |
| 845 | 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 | 887 | if (ret < 0) |
| 849 | 888 | goto end; |
| 850 | 889 | |