Browse code

avfilter: add yuvtestsrc source filter

Paul B Mahol authored on 2016/08/25 01:55:05
Showing 5 changed files
... ...
@@ -21,6 +21,7 @@ version <next>:
21 21
 - maskedclamp filter
22 22
 - hysteresis filter
23 23
 - lut2 filter
24
+- yuvtestsrc filter
24 25
 
25 26
 
26 27
 version 3.1:
... ...
@@ -14867,7 +14867,8 @@ ffplay -f lavfi life=s=300x200:mold=10:r=60:ratio=0.1:death_color=#C83232:life_c
14867 14867
 @anchor{smptehdbars}
14868 14868
 @anchor{testsrc}
14869 14869
 @anchor{testsrc2}
14870
-@section allrgb, allyuv, color, haldclutsrc, nullsrc, rgbtestsrc, smptebars, smptehdbars, testsrc, testsrc2
14870
+@anchor{yuvtestsrc}
14871
+@section allrgb, allyuv, color, haldclutsrc, nullsrc, rgbtestsrc, smptebars, smptehdbars, testsrc, testsrc2, yuvtestsrc
14871 14872
 
14872 14873
 The @code{allrgb} source returns frames of size 4096x4096 of all rgb colors.
14873 14874
 
... ...
@@ -14900,6 +14901,9 @@ The @code{testsrc2} source is similar to testsrc, but supports more
14900 14900
 pixel formats instead of just @code{rgb24}. This allows using it as an
14901 14901
 input for other tests without requiring a format conversion.
14902 14902
 
14903
+The @code{yuvtestsrc} source generates an YUV test pattern. You should
14904
+see a y, cb and cr stripe from top to bottom.
14905
+
14903 14906
 The sources accept the following parameters:
14904 14907
 
14905 14908
 @table @option
... ...
@@ -315,6 +315,7 @@ OBJS-$(CONFIG_SMPTEBARS_FILTER)              += vsrc_testsrc.o
315 315
 OBJS-$(CONFIG_SMPTEHDBARS_FILTER)            += vsrc_testsrc.o
316 316
 OBJS-$(CONFIG_TESTSRC_FILTER)                += vsrc_testsrc.o
317 317
 OBJS-$(CONFIG_TESTSRC2_FILTER)               += vsrc_testsrc.o
318
+OBJS-$(CONFIG_YUVTESTSRC_FILTER)             += vsrc_testsrc.o
318 319
 
319 320
 # multimedia filters
320 321
 OBJS-$(CONFIG_ADRAWGRAPH_FILTER)             += f_drawgraph.o
... ...
@@ -330,6 +330,7 @@ void avfilter_register_all(void)
330 330
     REGISTER_FILTER(SMPTEHDBARS,    smptehdbars,    vsrc);
331 331
     REGISTER_FILTER(TESTSRC,        testsrc,        vsrc);
332 332
     REGISTER_FILTER(TESTSRC2,       testsrc2,       vsrc);
333
+    REGISTER_FILTER(YUVTESTSRC,     yuvtestsrc,     vsrc);
333 334
 
334 335
     REGISTER_FILTER(NULLSINK,       nullsink,       vsink);
335 336
 
... ...
@@ -1070,6 +1070,182 @@ AVFilter ff_vsrc_rgbtestsrc = {
1070 1070
 
1071 1071
 #endif /* CONFIG_RGBTESTSRC_FILTER */
1072 1072
 
1073
+#if CONFIG_YUVTESTSRC_FILTER
1074
+
1075
+#define yuvtestsrc_options options
1076
+AVFILTER_DEFINE_CLASS(yuvtestsrc);
1077
+
1078
+static void yuvtest_fill_picture8(AVFilterContext *ctx, AVFrame *frame)
1079
+{
1080
+    int x, y, w = frame->width, h = frame->height / 3;
1081
+    const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(frame->format);
1082
+    const int factor = 1 << desc->comp[0].depth;
1083
+    const int mid = 1 << (desc->comp[0].depth - 1);
1084
+    uint8_t *ydst = frame->data[0];
1085
+    uint8_t *udst = frame->data[1];
1086
+    uint8_t *vdst = frame->data[2];
1087
+    int ylinesize = frame->linesize[0];
1088
+    int ulinesize = frame->linesize[1];
1089
+    int vlinesize = frame->linesize[2];
1090
+
1091
+    for (y = 0; y < h; y++) {
1092
+        for (x = 0; x < w; x++) {
1093
+            int c = factor * x / w;
1094
+
1095
+            ydst[x] = c;
1096
+            udst[x] = mid;
1097
+            vdst[x] = mid;
1098
+        }
1099
+
1100
+        ydst += ylinesize;
1101
+        udst += ulinesize;
1102
+        vdst += vlinesize;
1103
+    }
1104
+
1105
+    h += h;
1106
+    for (; y < h; y++) {
1107
+        for (x = 0; x < w; x++) {
1108
+            int c = factor * x / w;
1109
+
1110
+            ydst[x] = mid;
1111
+            udst[x] = c;
1112
+            vdst[x] = mid;
1113
+        }
1114
+
1115
+        ydst += ylinesize;
1116
+        udst += ulinesize;
1117
+        vdst += vlinesize;
1118
+    }
1119
+
1120
+    for (; y < frame->height; y++) {
1121
+        for (x = 0; x < w; x++) {
1122
+            int c = factor * x / w;
1123
+
1124
+            ydst[x] = mid;
1125
+            udst[x] = mid;
1126
+            vdst[x] = c;
1127
+        }
1128
+
1129
+        ydst += ylinesize;
1130
+        udst += ulinesize;
1131
+        vdst += vlinesize;
1132
+    }
1133
+}
1134
+
1135
+static void yuvtest_fill_picture16(AVFilterContext *ctx, AVFrame *frame)
1136
+{
1137
+    int x, y, w = frame->width, h = frame->height / 3;
1138
+    const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(frame->format);
1139
+    const int factor = 1 << desc->comp[0].depth;
1140
+    const int mid = 1 << (desc->comp[0].depth - 1);
1141
+    uint16_t *ydst = (uint16_t *)frame->data[0];
1142
+    uint16_t *udst = (uint16_t *)frame->data[1];
1143
+    uint16_t *vdst = (uint16_t *)frame->data[2];
1144
+    int ylinesize = frame->linesize[0] / 2;
1145
+    int ulinesize = frame->linesize[1] / 2;
1146
+    int vlinesize = frame->linesize[2] / 2;
1147
+
1148
+    for (y = 0; y < h; y++) {
1149
+        for (x = 0; x < w; x++) {
1150
+            int c = factor * x / w;
1151
+
1152
+            ydst[x] = c;
1153
+            udst[x] = mid;
1154
+            vdst[x] = mid;
1155
+        }
1156
+
1157
+        ydst += ylinesize;
1158
+        udst += ulinesize;
1159
+        vdst += vlinesize;
1160
+    }
1161
+
1162
+    h += h;
1163
+    for (; y < h; y++) {
1164
+        for (x = 0; x < w; x++) {
1165
+            int c = factor * x / w;
1166
+
1167
+            ydst[x] = mid;
1168
+            udst[x] = c;
1169
+            vdst[x] = mid;
1170
+        }
1171
+
1172
+        ydst += ylinesize;
1173
+        udst += ulinesize;
1174
+        vdst += vlinesize;
1175
+    }
1176
+
1177
+    for (; y < frame->height; y++) {
1178
+        for (x = 0; x < w; x++) {
1179
+            int c = factor * x / w;
1180
+
1181
+            ydst[x] = mid;
1182
+            udst[x] = mid;
1183
+            vdst[x] = c;
1184
+        }
1185
+
1186
+        ydst += ylinesize;
1187
+        udst += ulinesize;
1188
+        vdst += vlinesize;
1189
+    }
1190
+}
1191
+
1192
+static av_cold int yuvtest_init(AVFilterContext *ctx)
1193
+{
1194
+    TestSourceContext *test = ctx->priv;
1195
+
1196
+    test->draw_once = 1;
1197
+    return init(ctx);
1198
+}
1199
+
1200
+static int yuvtest_query_formats(AVFilterContext *ctx)
1201
+{
1202
+    static const enum AVPixelFormat pix_fmts[] = {
1203
+        AV_PIX_FMT_YUV444P, AV_PIX_FMT_YUVJ444P,
1204
+        AV_PIX_FMT_YUV444P9, AV_PIX_FMT_YUV444P10,
1205
+        AV_PIX_FMT_YUV444P12, AV_PIX_FMT_YUV444P14,
1206
+        AV_PIX_FMT_YUV444P16,
1207
+        AV_PIX_FMT_NONE
1208
+    };
1209
+
1210
+    AVFilterFormats *fmts_list = ff_make_format_list(pix_fmts);
1211
+    if (!fmts_list)
1212
+        return AVERROR(ENOMEM);
1213
+    return ff_set_common_formats(ctx, fmts_list);
1214
+}
1215
+
1216
+static int yuvtest_config_props(AVFilterLink *outlink)
1217
+{
1218
+    TestSourceContext *test = outlink->src->priv;
1219
+    const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(outlink->format);
1220
+
1221
+    test->fill_picture_fn = desc->comp[0].depth > 8 ? yuvtest_fill_picture16 : yuvtest_fill_picture8;
1222
+    return config_props(outlink);
1223
+}
1224
+
1225
+static const AVFilterPad avfilter_vsrc_yuvtestsrc_outputs[] = {
1226
+    {
1227
+        .name          = "default",
1228
+        .type          = AVMEDIA_TYPE_VIDEO,
1229
+        .request_frame = request_frame,
1230
+        .config_props  = yuvtest_config_props,
1231
+    },
1232
+    { NULL }
1233
+};
1234
+
1235
+AVFilter ff_vsrc_yuvtestsrc = {
1236
+    .name          = "yuvtestsrc",
1237
+    .description   = NULL_IF_CONFIG_SMALL("Generate YUV test pattern."),
1238
+    .priv_size     = sizeof(TestSourceContext),
1239
+    .priv_class    = &yuvtestsrc_class,
1240
+    .init          = yuvtest_init,
1241
+    .uninit        = uninit,
1242
+    .query_formats = yuvtest_query_formats,
1243
+    .inputs        = NULL,
1244
+    .outputs       = avfilter_vsrc_yuvtestsrc_outputs,
1245
+};
1246
+
1247
+#endif /* CONFIG_YUVTESTSRC_FILTER */
1248
+
1073 1249
 #if CONFIG_SMPTEBARS_FILTER || CONFIG_SMPTEHDBARS_FILTER
1074 1250
 
1075 1251
 static const uint8_t rainbow[7][4] = {