| @@ -54,6 +54,7 @@ enum DirectionMode { · 53 unmodified lines |
| 54 | 54 | enum SlideMode { |
| 55 | 55 | SLIDE_REPLACE, |
| 56 | 56 | SLIDE_SCROLL, |
| 57 | + SLIDE_FRAME, |
| 57 | 58 | NB_SLIDE |
| 58 | 59 | }; |
| 59 | 60 | |
| @@ -94,6 +95,7 @@ typedef struct ShowCWTContext { · 34 unmodified lines |
| 94 | 95 | int pps; |
| 95 | 96 | int eof; |
| 96 | 97 | int slide; |
| 98 | + int new_frame; |
| 97 | 99 | int direction; |
| 98 | 100 | int hop_size; |
| 99 | 101 | int hop_index; |
| @@ -138,6 +140,7 @@ static const AVOption showcwt_options[] = { · 38 unmodified lines |
| 138 | 140 | { "slide", "set slide mode", OFFSET(slide), AV_OPT_TYPE_INT, {.i64=0}, 0, NB_SLIDE-1, FLAGS, "slide" }, |
| 139 | 141 | { "replace", "replace", 0, AV_OPT_TYPE_CONST,{.i64=SLIDE_REPLACE},0, 0, FLAGS, "slide" }, |
| 140 | 142 | { "scroll", "scroll", 0, AV_OPT_TYPE_CONST,{.i64=SLIDE_SCROLL}, 0, 0, FLAGS, "slide" }, |
| 143 | + { "frame", "frame", 0, AV_OPT_TYPE_CONST,{.i64=SLIDE_FRAME}, 0, 0, FLAGS, "slide" }, |
| 141 | 144 | { "direction", "set direction mode", OFFSET(direction), AV_OPT_TYPE_INT, {.i64=0}, 0, NB_DIRECTION-1, FLAGS, "direction" }, |
| 142 | 145 | { "lr", "left to right", 0, AV_OPT_TYPE_CONST,{.i64=DIRECTION_LR}, 0, 0, FLAGS, "direction" }, |
| 143 | 146 | { "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) · 186 unmodified lines |
| 330 | 333 | |
| 331 | 334 | switch (s->slide) { |
| 332 | 335 | case SLIDE_REPLACE: |
| 336 | + case SLIDE_FRAME: |
| 333 | 337 | /* nothing to do here */ |
| 334 | 338 | break; |
| 335 | 339 | case SLIDE_SCROLL: |
| @@ -515,6 +519,7 @@ static int config_output(AVFilterLink *outlink) · 179 unmodified lines |
| 515 | 519 | break; |
| 516 | 520 | } |
| 517 | 521 | |
| 522 | + s->new_frame = 1; |
| 518 | 523 | s->nb_threads = FFMIN(s->frequency_band_count, ff_filter_get_nb_threads(ctx)); |
| 519 | 524 | s->nb_channels = inlink->ch_layout.nb_channels; |
| 520 | 525 | s->old_pts = AV_NOPTS_VALUE; |
| @@ -675,7 +680,6 @@ static int output_frame(AVFilterContext *ctx) · 154 unmodified lines |
| 675 | 680 | AVFilterLink *outlink = ctx->outputs[0]; |
| 676 | 681 | AVFilterLink *inlink = ctx->inputs[0]; |
| 677 | 682 | ShowCWTContext *s = ctx->priv; |
| 678 | | − int64_t pts_offset; |
| 679 | 683 | int ret; |
| 680 | 684 | |
| 681 | 685 | switch (s->slide) { |
| @@ -709,35 +713,37 @@ static int output_frame(AVFilterContext *ctx) · 27 unmodified lines |
| 709 | 713 | |
| 710 | 714 | ff_filter_execute(ctx, draw, NULL, NULL, s->nb_threads); |
| 711 | 715 | |
| 712 | | − pts_offset = av_rescale(s->ihop_index, s->hop_size, s->ihop_size); |
| 713 | | − s->outpicref->pts = av_rescale_q(s->in_pts + pts_offset, inlink->time_base, outlink->time_base); |
| 714 | | − |
| 715 | | − s->ihop_index++; |
| 716 | | − if (s->ihop_index >= s->ihop_size) |
| 717 | | − s->ihop_index = 0; |
| 718 | | − |
| 719 | 716 | switch (s->slide) { |
| 720 | 717 | case SLIDE_REPLACE: |
| 718 | + case SLIDE_FRAME: |
| 721 | 719 | switch (s->direction) { |
| 722 | 720 | case DIRECTION_LR: |
| 723 | 721 | s->pos++; |
| 724 | | − if (s->pos >= s->w) |
| 722 | + if (s->pos >= s->w) { |
| 725 | 723 | s->pos = 0; |
| 724 | + s->new_frame = 1; |
| 725 | + } |
| 726 | 726 | break; |
| 727 | 727 | case DIRECTION_RL: |
| 728 | 728 | s->pos--; |
| 729 | | − if (s->pos < 0) |
| 729 | + if (s->pos < 0) { |
| 730 | 730 | s->pos = s->w - 1; |
| 731 | + s->new_frame = 1; |
| 732 | + } |
| 731 | 733 | break; |
| 732 | 734 | case DIRECTION_UD: |
| 733 | 735 | s->pos++; |
| 734 | | − if (s->pos >= s->h) |
| 736 | + if (s->pos >= s->h) { |
| 735 | 737 | s->pos = 0; |
| 738 | + s->new_frame = 1; |
| 739 | + } |
| 736 | 740 | break; |
| 737 | 741 | case DIRECTION_DU: |
| 738 | 742 | s->pos--; |
| 739 | | − if (s->pos < 0) |
| 743 | + if (s->pos < 0) { |
| 740 | 744 | s->pos = s->h - 1; |
| 745 | + s->new_frame = 1; |
| 746 | + } |
| 741 | 747 | break; |
| 742 | 748 | } |
| 743 | 749 | break; |
| @@ -757,6 +763,77 @@ static int output_frame(AVFilterContext *ctx) · 13 unmodified lines |
| 757 | 763 | break; |
| 758 | 764 | } |
| 759 | 765 | |
| 766 | + if (s->slide == SLIDE_FRAME && s->eof) { |
| 767 | + switch (s->direction) { |
| 768 | + case DIRECTION_LR: |
| 769 | + for (int p = 0; p < 3; p++) { |
| 770 | + ptrdiff_t linesize = s->outpicref->linesize[p]; |
| 771 | + const int size = s->w - s->pos; |
| 772 | + const int fill = p ? 128 : 0; |
| 773 | + const int x = s->pos; |
| 774 | + |
| 775 | + for (int y = 0; y < s->h; y++) { |
| 776 | + uint8_t *dst = s->outpicref->data[p] + y * linesize + x; |
| 777 | + |
| 778 | + memset(dst, fill, size); |
| 779 | + } |
| 780 | + } |
| 781 | + break; |
| 782 | + case DIRECTION_RL: |
| 783 | + for (int p = 0; p < 3; p++) { |
| 784 | + ptrdiff_t linesize = s->outpicref->linesize[p]; |
| 785 | + const int size = s->w - s->pos; |
| 786 | + const int fill = p ? 128 : 0; |
| 787 | + |
| 788 | + for (int y = 0; y < s->h; y++) { |
| 789 | + uint8_t *dst = s->outpicref->data[p] + y * linesize; |
| 790 | + |
| 791 | + memset(dst, fill, size); |
| 792 | + } |
| 793 | + } |
| 794 | + break; |
| 795 | + case DIRECTION_UD: |
| 796 | + for (int p = 0; p < 3; p++) { |
| 797 | + ptrdiff_t linesize = s->outpicref->linesize[p]; |
| 798 | + const int fill = p ? 128 : 0; |
| 799 | + |
| 800 | + for (int y = s->pos; y < s->h; y++) { |
| 801 | + uint8_t *dst = s->outpicref->data[p] + y * linesize; |
| 802 | + |
| 803 | + memset(dst, fill, s->w); |
| 804 | + } |
| 805 | + } |
| 806 | + break; |
| 807 | + case DIRECTION_DU: |
| 808 | + for (int p = 0; p < 3; p++) { |
| 809 | + ptrdiff_t linesize = s->outpicref->linesize[p]; |
| 810 | + const int fill = p ? 128 : 0; |
| 811 | + |
| 812 | + for (int y = s->h - s->pos; y >= 0; y--) { |
| 813 | + uint8_t *dst = s->outpicref->data[p] + y * linesize; |
| 814 | + |
| 815 | + memset(dst, fill, s->w); |
| 816 | + } |
| 817 | + } |
| 818 | + break; |
| 819 | + } |
| 820 | + } |
| 821 | + |
| 822 | + s->new_frame = s->slide == SLIDE_FRAME && (s->new_frame || s->eof); |
| 823 | + |
| 824 | + if (s->slide != SLIDE_FRAME || s->new_frame == 1) { |
| 825 | + int64_t pts_offset = s->new_frame ? 0LL : av_rescale(s->ihop_index, s->hop_size, s->ihop_size); |
| 826 | + |
| 827 | + s->outpicref->pts = av_rescale_q(s->in_pts + pts_offset, inlink->time_base, outlink->time_base); |
| 828 | + } |
| 829 | + |
| 830 | + s->ihop_index++; |
| 831 | + if (s->ihop_index >= s->ihop_size) |
| 832 | + s->ihop_index = 0; |
| 833 | + |
| 834 | + if (s->slide == SLIDE_FRAME && s->new_frame == 0) |
| 835 | + return 1; |
| 836 | + |
| 760 | 837 | if (s->old_pts < s->outpicref->pts) { |
| 761 | 838 | AVFrame *out = ff_get_video_buffer(outlink, outlink->w, outlink->h); |
| 762 | 839 | if (!out) |
| @@ -768,6 +845,7 @@ static int output_frame(AVFilterContext *ctx) · 5 unmodified lines |
| 768 | 845 | if (ret < 0) |
| 769 | 846 | goto fail; |
| 770 | 847 | s->old_pts = s->outpicref->pts; |
| 848 | + s->new_frame = 0; |
| 771 | 849 | ret = ff_filter_frame(outlink, out); |
| 772 | 850 | if (ret <= 0) |
| 773 | 851 | return ret; |
| @@ -816,8 +894,10 @@ static int activate(AVFilterContext *ctx) · 42 unmodified lines |
| 816 | 894 | ff_filter_execute(ctx, run_channels_cwt_prepare, fin, NULL, |
| 817 | 895 | FFMIN(s->nb_threads, s->nb_channels)); |
| 818 | 896 | if (fin) { |
| 819 | | − if (s->hop_index == 0) |
| 897 | + if ((s->hop_index == 0 && s->slide != SLIDE_FRAME) || s->new_frame) { |
| 820 | 898 | s->in_pts = fin->pts; |
| 899 | + s->new_frame = 0; |
| 900 | + } |
| 821 | 901 | s->hop_index += fin->nb_samples; |
| 822 | 902 | av_frame_free(&fin); |
| 823 | 903 | } else { |
| @@ -843,9 +923,12 @@ static int activate(AVFilterContext *ctx) · 19 unmodified lines |
| 843 | 923 | } |
| 844 | 924 | } |
| 845 | 925 | |
| 846 | | − if (s->eof && s->eof_pts != AV_NOPTS_VALUE && s->old_pts + 1 >= s->eof_pts) { |
| 926 | + if (s->eof && s->eof_pts != AV_NOPTS_VALUE && |
| 927 | + (s->old_pts + 1 >= s->eof_pts || (s->slide == SLIDE_FRAME))) { |
| 928 | + if (s->slide == SLIDE_FRAME) |
| 929 | + ret = output_frame(ctx); |
| 847 | 930 | ff_outlink_set_status(outlink, AVERROR_EOF, s->eof_pts); |
| 848 | | − return 0; |
| 931 | + return ret; |
| 849 | 932 | } |
| 850 | 933 | |
| 851 | 934 | if (!s->eof && ff_inlink_acknowledge_status(inlink, &status, &pts)) { |