Signed-off-by: Paul B Mahol <onemda@gmail.com>
Paul B Mahol authored on 2016/02/29 19:32:17... | ... |
@@ -12559,6 +12559,28 @@ can still spot out of range values without constantly looking at vectorscope. |
12559 | 12559 |
@item peak+instant |
12560 | 12560 |
Peak and instant envelope combined together. |
12561 | 12561 |
@end table |
12562 |
+ |
|
12563 |
+@item graticule, g |
|
12564 |
+Set what kind of graticule to draw. |
|
12565 |
+@table @samp |
|
12566 |
+@item none |
|
12567 |
+@item green |
|
12568 |
+@item color |
|
12569 |
+@end table |
|
12570 |
+ |
|
12571 |
+@item opacity, o |
|
12572 |
+Set graticule opacity. |
|
12573 |
+ |
|
12574 |
+@item flags, f |
|
12575 |
+Set graticule flags. |
|
12576 |
+ |
|
12577 |
+@table @samp |
|
12578 |
+@item white |
|
12579 |
+Draw graticule for white point. |
|
12580 |
+ |
|
12581 |
+@item black |
|
12582 |
+Draw graticule for black point. |
|
12583 |
+@end table |
|
12562 | 12584 |
@end table |
12563 | 12585 |
|
12564 | 12586 |
@anchor{vidstabdetect} |
... | ... |
@@ -50,12 +50,19 @@ typedef struct VectorscopeContext { |
50 | 50 |
int x, y, pd; |
51 | 51 |
int is_yuv; |
52 | 52 |
int size; |
53 |
+ int depth; |
|
53 | 54 |
int mult; |
54 | 55 |
int envelope; |
56 |
+ int graticule; |
|
57 |
+ float opacity; |
|
58 |
+ int flags; |
|
59 |
+ int cs; |
|
55 | 60 |
uint8_t peak[1024][1024]; |
56 | 61 |
|
57 | 62 |
void (*vectorscope)(struct VectorscopeContext *s, |
58 | 63 |
AVFrame *in, AVFrame *out, int pd); |
64 |
+ void (*graticulef)(struct VectorscopeContext *s, AVFrame *out, |
|
65 |
+ int X, int Y, int D, int P); |
|
59 | 66 |
} VectorscopeContext; |
60 | 67 |
|
61 | 68 |
#define OFFSET(x) offsetof(VectorscopeContext, x) |
... | ... |
@@ -80,6 +87,17 @@ static const AVOption vectorscope_options[] = { |
80 | 80 |
{ "instant", 0, 0, AV_OPT_TYPE_CONST, {.i64=1}, 0, 0, FLAGS, "envelope" }, |
81 | 81 |
{ "peak", 0, 0, AV_OPT_TYPE_CONST, {.i64=2}, 0, 0, FLAGS, "envelope" }, |
82 | 82 |
{ "peak+instant", 0, 0, AV_OPT_TYPE_CONST, {.i64=3}, 0, 0, FLAGS, "envelope" }, |
83 |
+ { "graticule", "set graticule", OFFSET(graticule), AV_OPT_TYPE_INT, {.i64=0}, 0, 2, FLAGS, "graticule"}, |
|
84 |
+ { "g", "set graticule", OFFSET(graticule), AV_OPT_TYPE_INT, {.i64=0}, 0, 2, FLAGS, "graticule"}, |
|
85 |
+ { "none", 0, 0, AV_OPT_TYPE_CONST, {.i64=0}, 0, 0, FLAGS, "graticule" }, |
|
86 |
+ { "green", 0, 0, AV_OPT_TYPE_CONST, {.i64=1}, 0, 0, FLAGS, "graticule" }, |
|
87 |
+ { "color", 0, 0, AV_OPT_TYPE_CONST, {.i64=2}, 0, 0, FLAGS, "graticule" }, |
|
88 |
+ { "opacity", "set graticule opacity", OFFSET(opacity), AV_OPT_TYPE_FLOAT, {.dbl=0.75}, 0, 1, FLAGS}, |
|
89 |
+ { "o", "set graticule opacity", OFFSET(opacity), AV_OPT_TYPE_FLOAT, {.dbl=0.75}, 0, 1, FLAGS}, |
|
90 |
+ { "flags", "set graticule flags", OFFSET(flags), AV_OPT_TYPE_FLAGS, {.i64=0}, 0, 3, FLAGS, "flags"}, |
|
91 |
+ { "f", "set graticule flags", OFFSET(flags), AV_OPT_TYPE_FLAGS, {.i64=0}, 0, 3, FLAGS, "flags"}, |
|
92 |
+ { "white", "draw white point", 0, AV_OPT_TYPE_CONST, {.i64=1}, 0, 0, FLAGS, "flags" }, |
|
93 |
+ { "black", "draw black point", 0, AV_OPT_TYPE_CONST, {.i64=2}, 0, 0, FLAGS, "flags" }, |
|
83 | 94 |
{ NULL } |
84 | 95 |
}; |
85 | 96 |
|
... | ... |
@@ -662,6 +680,228 @@ static void vectorscope8(VectorscopeContext *s, AVFrame *in, AVFrame *out, int p |
662 | 662 |
} |
663 | 663 |
} |
664 | 664 |
|
665 |
+const static uint16_t positions[][14][3] = { |
|
666 |
+ { { 210, 16, 146 }, { 170, 166, 16 }, { 145, 54, 34 }, |
|
667 |
+ { 106, 202, 222 }, { 81, 90, 240 }, { 41, 240, 110 }, |
|
668 |
+ { 162, 44, 142 }, { 131, 156, 44 }, { 112, 72, 58 }, |
|
669 |
+ { 84, 184, 198 }, { 65, 100, 212 }, { 35, 212, 114 }, |
|
670 |
+ { 235, 128, 128 }, { 16, 128, 128 } }, |
|
671 |
+ { { 63, 102, 240 }, { 32, 240, 118 }, { 188, 154, 16 }, |
|
672 |
+ { 219, 16, 138 }, { 173, 42, 26 }, { 78, 214, 230 }, |
|
673 |
+ { 28, 212, 120 }, { 51, 109, 212 }, { 63, 193, 204 }, |
|
674 |
+ { 133, 63, 52 }, { 145, 147, 44 }, { 168, 44, 136 }, |
|
675 |
+ { 235, 128, 128 }, { 16, 128, 128 } }, |
|
676 |
+ { { 210*2, 16*2, 146*2 }, { 170*2, 166*2, 16*2 }, { 145*2, 54*2, 34*2 }, |
|
677 |
+ { 106*2, 202*2, 222*2 }, { 81*2, 90*2, 240*2 }, { 41*2, 240*2, 110*2 }, |
|
678 |
+ { 162*2, 44*2, 142*2 }, { 131*2, 156*2, 44*2 }, { 112*2, 72*2, 58*2 }, |
|
679 |
+ { 84*2, 184*2, 198*2 }, { 65*2, 100*2, 212*2 }, { 35*2, 212*2, 114*2 }, |
|
680 |
+ { 470, 256, 256 }, { 32, 256, 256 } }, |
|
681 |
+ { { 63*2, 102*2, 240*2 }, { 32*2, 240*2, 118*2 }, { 188*2, 154*2, 16*2 }, |
|
682 |
+ { 219*2, 16*2, 138*2 }, { 173*2, 42*2, 26*2 }, { 78*2, 214*2, 230*2 }, |
|
683 |
+ { 28*2, 212*2, 120*2 }, { 51*2, 109*2, 212*2 }, { 63*2, 193*2, 204*2 }, |
|
684 |
+ { 133*2, 63*2, 52*2 }, { 145*2, 147*2, 44*2 }, { 168*2, 44*2, 136*2 }, |
|
685 |
+ { 470, 256, 256 }, { 32, 256, 256 } }, |
|
686 |
+ { { 210*4, 16*4, 146*4 }, { 170*4, 166*4, 16*4 }, { 145*4, 54*4, 34*4 }, |
|
687 |
+ { 106*4, 202*4, 222*4 }, { 81*4, 90*4, 240*4 }, { 41*4, 240*4, 110*4 }, |
|
688 |
+ { 162*4, 44*4, 142*4 }, { 131*4, 156*4, 44*4 }, { 112*4, 72*4, 58*4 }, |
|
689 |
+ { 84*4, 184*4, 198*4 }, { 65*4, 100*4, 212*4 }, { 35*4, 212*4, 114*4 }, |
|
690 |
+ { 940, 512, 512 }, { 64, 512, 512 } }, |
|
691 |
+ { { 63*4, 102*4, 240*4 }, { 32*4, 240*4, 118*4 }, { 188*4, 154*4, 16*4 }, |
|
692 |
+ { 219*4, 16*4, 138*4 }, { 173*4, 42*4, 26*4 }, { 78*4, 214*4, 230*4 }, |
|
693 |
+ { 28*4, 212*4, 120*4 }, { 51*4, 109*4, 212*4 }, { 63*4, 193*4, 204*4 }, |
|
694 |
+ { 133*4, 63*4, 52*4 }, { 145*4, 147*4, 44*4 }, { 168*4, 44*4, 136*4 }, |
|
695 |
+ { 940, 512, 512 }, { 64, 512, 512 } }, |
|
696 |
+}; |
|
697 |
+ |
|
698 |
+static void draw_dots(uint8_t *dst, int L, int v, float o) |
|
699 |
+{ |
|
700 |
+ const float f = 1. - o; |
|
701 |
+ const float V = o * v; |
|
702 |
+ int l = L * 2; |
|
703 |
+ |
|
704 |
+ dst[ l - 3] = dst[ l - 3] * f + V; |
|
705 |
+ dst[ l + 3] = dst[ l + 3] * f + V; |
|
706 |
+ dst[-l - 3] = dst[-l - 3] * f + V; |
|
707 |
+ dst[-l + 3] = dst[-l + 3] * f + V; |
|
708 |
+ |
|
709 |
+ l += L; |
|
710 |
+ |
|
711 |
+ dst[ l - 3] = dst[ l - 3] * f + V; |
|
712 |
+ dst[ l + 3] = dst[ l + 3] * f + V; |
|
713 |
+ dst[ l - 2] = dst[ l - 2] * f + V; |
|
714 |
+ dst[ l + 2] = dst[ l + 2] * f + V; |
|
715 |
+ dst[-l - 3] = dst[-l - 3] * f + V; |
|
716 |
+ dst[-l + 3] = dst[-l + 3] * f + V; |
|
717 |
+ dst[-l - 2] = dst[-l - 2] * f + V; |
|
718 |
+ dst[-l + 2] = dst[-l + 2] * f + V; |
|
719 |
+} |
|
720 |
+ |
|
721 |
+static void draw_dots16(uint16_t *dst, int L, int v, float o) |
|
722 |
+{ |
|
723 |
+ const float f = 1. - o; |
|
724 |
+ const float V = o * v; |
|
725 |
+ int l = L * 2; |
|
726 |
+ |
|
727 |
+ dst[ l - 3] = dst[ l - 3] * f + V; |
|
728 |
+ dst[ l + 3] = dst[ l + 3] * f + V; |
|
729 |
+ dst[-l - 3] = dst[-l - 3] * f + V; |
|
730 |
+ dst[-l + 3] = dst[-l + 3] * f + V; |
|
731 |
+ |
|
732 |
+ l += L; |
|
733 |
+ |
|
734 |
+ dst[ l - 3] = dst[ l - 3] * f + V; |
|
735 |
+ dst[ l + 3] = dst[ l + 3] * f + V; |
|
736 |
+ dst[ l - 2] = dst[ l - 2] * f + V; |
|
737 |
+ dst[ l + 2] = dst[ l + 2] * f + V; |
|
738 |
+ dst[-l - 3] = dst[-l - 3] * f + V; |
|
739 |
+ dst[-l + 3] = dst[-l + 3] * f + V; |
|
740 |
+ dst[-l - 2] = dst[-l - 2] * f + V; |
|
741 |
+ dst[-l + 2] = dst[-l + 2] * f + V; |
|
742 |
+} |
|
743 |
+ |
|
744 |
+static void none_graticule(VectorscopeContext *s, AVFrame *out, int X, int Y, int D, int P) |
|
745 |
+{ |
|
746 |
+} |
|
747 |
+ |
|
748 |
+static void color_graticule16(VectorscopeContext *s, AVFrame *out, int X, int Y, int D, int P) |
|
749 |
+{ |
|
750 |
+ const float o = s->opacity; |
|
751 |
+ int i; |
|
752 |
+ |
|
753 |
+ for (i = 0; i < 12; i++) { |
|
754 |
+ int x = positions[P][i][X]; |
|
755 |
+ int y = positions[P][i][Y]; |
|
756 |
+ int d = positions[P][i][D]; |
|
757 |
+ |
|
758 |
+ draw_dots16((uint16_t *)(out->data[D] + y * out->linesize[D] + x * 2), out->linesize[D] / 2, d, o); |
|
759 |
+ draw_dots16((uint16_t *)(out->data[X] + y * out->linesize[X] + x * 2), out->linesize[X] / 2, x, o); |
|
760 |
+ draw_dots16((uint16_t *)(out->data[Y] + y * out->linesize[Y] + x * 2), out->linesize[Y] / 2, y, o); |
|
761 |
+ } |
|
762 |
+ |
|
763 |
+ if (s->flags & 1) { |
|
764 |
+ int x = positions[P][12][X]; |
|
765 |
+ int y = positions[P][12][Y]; |
|
766 |
+ int d = positions[P][12][D]; |
|
767 |
+ |
|
768 |
+ draw_dots16((uint16_t *)(out->data[D] + y * out->linesize[D] + x * 2), out->linesize[D] / 2, d, o); |
|
769 |
+ draw_dots16((uint16_t *)(out->data[X] + y * out->linesize[X] + x * 2), out->linesize[X] / 2, x, o); |
|
770 |
+ draw_dots16((uint16_t *)(out->data[Y] + y * out->linesize[Y] + x * 2), out->linesize[Y] / 2, y, o); |
|
771 |
+ } |
|
772 |
+ |
|
773 |
+ if (s->flags & 2) { |
|
774 |
+ int x = positions[P][13][X]; |
|
775 |
+ int y = positions[P][13][Y]; |
|
776 |
+ int d = positions[P][13][D]; |
|
777 |
+ |
|
778 |
+ draw_dots16((uint16_t *)(out->data[D] + y * out->linesize[D] + x * 2), out->linesize[D] / 2, d, o); |
|
779 |
+ draw_dots16((uint16_t *)(out->data[X] + y * out->linesize[X] + x * 2), out->linesize[X] / 2, x, o); |
|
780 |
+ draw_dots16((uint16_t *)(out->data[Y] + y * out->linesize[Y] + x * 2), out->linesize[Y] / 2, y, o); |
|
781 |
+ } |
|
782 |
+} |
|
783 |
+ |
|
784 |
+static void color_graticule(VectorscopeContext *s, AVFrame *out, int X, int Y, int D, int P) |
|
785 |
+{ |
|
786 |
+ const float o = s->opacity; |
|
787 |
+ int i; |
|
788 |
+ |
|
789 |
+ for (i = 0; i < 12; i++) { |
|
790 |
+ int x = positions[P][i][X]; |
|
791 |
+ int y = positions[P][i][Y]; |
|
792 |
+ int d = positions[P][i][D]; |
|
793 |
+ |
|
794 |
+ draw_dots(out->data[D] + y * out->linesize[D] + x, out->linesize[D], d, o); |
|
795 |
+ draw_dots(out->data[X] + y * out->linesize[X] + x, out->linesize[X], x, o); |
|
796 |
+ draw_dots(out->data[Y] + y * out->linesize[Y] + x, out->linesize[Y], y, o); |
|
797 |
+ } |
|
798 |
+ |
|
799 |
+ if (s->flags & 1) { |
|
800 |
+ int x = positions[P][12][X]; |
|
801 |
+ int y = positions[P][12][Y]; |
|
802 |
+ int d = positions[P][12][D]; |
|
803 |
+ |
|
804 |
+ draw_dots(out->data[D] + y * out->linesize[D] + x, out->linesize[D], d, o); |
|
805 |
+ draw_dots(out->data[X] + y * out->linesize[X] + x, out->linesize[X], x, o); |
|
806 |
+ draw_dots(out->data[Y] + y * out->linesize[Y] + x, out->linesize[Y], y, o); |
|
807 |
+ } |
|
808 |
+ |
|
809 |
+ if (s->flags & 2) { |
|
810 |
+ int x = positions[P][13][X]; |
|
811 |
+ int y = positions[P][13][Y]; |
|
812 |
+ int d = positions[P][12][D]; |
|
813 |
+ |
|
814 |
+ draw_dots(out->data[D] + y * out->linesize[D] + x, out->linesize[D], d, o); |
|
815 |
+ draw_dots(out->data[X] + y * out->linesize[X] + x, out->linesize[X], x, o); |
|
816 |
+ draw_dots(out->data[Y] + y * out->linesize[Y] + x, out->linesize[Y], y, o); |
|
817 |
+ } |
|
818 |
+} |
|
819 |
+ |
|
820 |
+static void green_graticule16(VectorscopeContext *s, AVFrame *out, int X, int Y, int D, int P) |
|
821 |
+{ |
|
822 |
+ const float o = s->opacity; |
|
823 |
+ const int m = s->mult; |
|
824 |
+ int i; |
|
825 |
+ |
|
826 |
+ for (i = 0; i < 12; i++) { |
|
827 |
+ int x = positions[P][i][X]; |
|
828 |
+ int y = positions[P][i][Y]; |
|
829 |
+ |
|
830 |
+ draw_dots16((uint16_t *)(out->data[D] + y * out->linesize[D] + x * 2), out->linesize[D] / 2, 128 * m, o); |
|
831 |
+ draw_dots16((uint16_t *)(out->data[X] + y * out->linesize[X] + x * 2), out->linesize[X] / 2, 0, o); |
|
832 |
+ draw_dots16((uint16_t *)(out->data[Y] + y * out->linesize[Y] + x * 2), out->linesize[Y] / 2, 0, o); |
|
833 |
+ } |
|
834 |
+ |
|
835 |
+ if (s->flags & 1) { |
|
836 |
+ int x = positions[P][12][X]; |
|
837 |
+ int y = positions[P][12][Y]; |
|
838 |
+ |
|
839 |
+ draw_dots16((uint16_t *)(out->data[D] + y * out->linesize[D] + x * 2), out->linesize[D] / 2, 128 * m, o); |
|
840 |
+ draw_dots16((uint16_t *)(out->data[X] + y * out->linesize[X] + x * 2), out->linesize[X] / 2, 0, o); |
|
841 |
+ draw_dots16((uint16_t *)(out->data[Y] + y * out->linesize[Y] + x * 2), out->linesize[Y] / 2, 0, o); |
|
842 |
+ } |
|
843 |
+ |
|
844 |
+ if (s->flags & 2) { |
|
845 |
+ int x = positions[P][13][X]; |
|
846 |
+ int y = positions[P][13][Y]; |
|
847 |
+ |
|
848 |
+ draw_dots16((uint16_t *)(out->data[D] + y * out->linesize[D] + x * 2), out->linesize[D] / 2, 128 * m, o); |
|
849 |
+ draw_dots16((uint16_t *)(out->data[X] + y * out->linesize[X] + x * 2), out->linesize[X] / 2, 0, o); |
|
850 |
+ draw_dots16((uint16_t *)(out->data[Y] + y * out->linesize[Y] + x * 2), out->linesize[Y] / 2, 0, o); |
|
851 |
+ } |
|
852 |
+} |
|
853 |
+ |
|
854 |
+static void green_graticule(VectorscopeContext *s, AVFrame *out, int X, int Y, int D, int P) |
|
855 |
+{ |
|
856 |
+ const float o = s->opacity; |
|
857 |
+ int i; |
|
858 |
+ |
|
859 |
+ for (i = 0; i < 12; i++) { |
|
860 |
+ int x = positions[P][i][X]; |
|
861 |
+ int y = positions[P][i][Y]; |
|
862 |
+ |
|
863 |
+ draw_dots(out->data[D] + y * out->linesize[D] + x, out->linesize[D], 128, o); |
|
864 |
+ draw_dots(out->data[X] + y * out->linesize[X] + x, out->linesize[X], 0, o); |
|
865 |
+ draw_dots(out->data[Y] + y * out->linesize[Y] + x, out->linesize[Y], 0, o); |
|
866 |
+ } |
|
867 |
+ |
|
868 |
+ if (s->flags & 1) { |
|
869 |
+ int x = positions[P][12][X]; |
|
870 |
+ int y = positions[P][12][Y]; |
|
871 |
+ |
|
872 |
+ draw_dots(out->data[D] + y * out->linesize[D] + x, out->linesize[D], 128, o); |
|
873 |
+ draw_dots(out->data[X] + y * out->linesize[X] + x, out->linesize[X], 0, o); |
|
874 |
+ draw_dots(out->data[Y] + y * out->linesize[Y] + x, out->linesize[Y], 0, o); |
|
875 |
+ } |
|
876 |
+ |
|
877 |
+ if (s->flags & 2) { |
|
878 |
+ int x = positions[P][13][X]; |
|
879 |
+ int y = positions[P][13][Y]; |
|
880 |
+ |
|
881 |
+ draw_dots(out->data[D] + y * out->linesize[D] + x, out->linesize[D], 128, o); |
|
882 |
+ draw_dots(out->data[X] + y * out->linesize[X] + x, out->linesize[X], 0, o); |
|
883 |
+ draw_dots(out->data[Y] + y * out->linesize[Y] + x, out->linesize[Y], 0, o); |
|
884 |
+ } |
|
885 |
+} |
|
886 |
+ |
|
665 | 887 |
static int filter_frame(AVFilterLink *inlink, AVFrame *in) |
666 | 888 |
{ |
667 | 889 |
AVFilterContext *ctx = inlink->dst; |
... | ... |
@@ -669,6 +909,16 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in) |
669 | 669 |
AVFilterLink *outlink = ctx->outputs[0]; |
670 | 670 |
AVFrame *out; |
671 | 671 |
|
672 |
+ switch (av_frame_get_colorspace(in)) { |
|
673 |
+ case AVCOL_SPC_SMPTE170M: |
|
674 |
+ case AVCOL_SPC_BT470BG: |
|
675 |
+ s->cs = (s->depth - 8) * 2 + 0; |
|
676 |
+ break; |
|
677 |
+ case AVCOL_SPC_BT709: |
|
678 |
+ default: |
|
679 |
+ s->cs = (s->depth - 8) * 2 + 1; |
|
680 |
+ } |
|
681 |
+ |
|
672 | 682 |
out = ff_get_video_buffer(outlink, outlink->w, outlink->h); |
673 | 683 |
if (!out) { |
674 | 684 |
av_frame_free(&in); |
... | ... |
@@ -677,6 +927,7 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in) |
677 | 677 |
out->pts = in->pts; |
678 | 678 |
|
679 | 679 |
s->vectorscope(s, in, out, s->pd); |
680 |
+ s->graticulef(s, out, s->x, s->y, s->pd, s->cs); |
|
680 | 681 |
|
681 | 682 |
av_frame_free(&in); |
682 | 683 |
return ff_filter_frame(outlink, out); |
... | ... |
@@ -690,6 +941,7 @@ static int config_input(AVFilterLink *inlink) |
690 | 690 |
s->is_yuv = !(desc->flags & AV_PIX_FMT_FLAG_RGB); |
691 | 691 |
s->size = 1 << desc->comp[0].depth; |
692 | 692 |
s->mult = s->size / 256; |
693 |
+ s->depth = desc->comp[0].depth; |
|
693 | 694 |
|
694 | 695 |
if (s->mode == GRAY && s->is_yuv) |
695 | 696 |
s->pd = 0; |
... | ... |
@@ -707,6 +959,20 @@ static int config_input(AVFilterLink *inlink) |
707 | 707 |
else |
708 | 708 |
s->vectorscope = vectorscope16; |
709 | 709 |
|
710 |
+ s->graticulef = none_graticule; |
|
711 |
+ |
|
712 |
+ if (s->is_yuv && s->size == 256) { |
|
713 |
+ if (s->graticule == 1) |
|
714 |
+ s->graticulef = green_graticule; |
|
715 |
+ else if (s->graticule == 2) |
|
716 |
+ s->graticulef = color_graticule; |
|
717 |
+ } else if (s->is_yuv) { |
|
718 |
+ if (s->graticule == 1) |
|
719 |
+ s->graticulef = green_graticule16; |
|
720 |
+ else if (s->graticule == 2) |
|
721 |
+ s->graticulef = color_graticule16; |
|
722 |
+ } |
|
723 |
+ |
|
710 | 724 |
switch (inlink->format) { |
711 | 725 |
case AV_PIX_FMT_GBRP10: |
712 | 726 |
case AV_PIX_FMT_GBRP9: |