User may set color range / matrix coefficient set / primaries / transfer characteristics for output.
Unified · Split
| @@ -61,6 +61,8 @@ typedef struct VPPContext{ · 60 unmodified lines | |||
| 61 | #if QSV_ONEVPL | 61 | #if QSV_ONEVPL |
| 62 | /** Video signal info attached on the input frame */ | 62 | /** Video signal info attached on the input frame */ |
| 63 | mfxExtVideoSignalInfo invsi_conf; | 63 | mfxExtVideoSignalInfo invsi_conf; |
| 64 | /** Video signal info attached on the output frame */ | ||
| 65 | mfxExtVideoSignalInfo outvsi_conf; | ||
| 64 | #endif | 66 | #endif |
| 65 | 67 | ||
| 66 | /** | 68 | /** |
| @@ -104,6 +106,16 @@ typedef struct VPPContext{ · 37 unmodified lines | |||
| 104 | char *ow, *oh; | 106 | char *ow, *oh; |
| 105 | char *output_format_str; | 107 | char *output_format_str; |
| 106 | 108 | ||
| 109 | /** The color properties for output */ | ||
| 110 | char *color_primaries_str; | ||
| 111 | char *color_transfer_str; | ||
| 112 | char *color_matrix_str; | ||
| 113 | |||
| 114 | int color_range; | ||
| 115 | enum AVColorPrimaries color_primaries; | ||
| 116 | enum AVColorTransferCharacteristic color_transfer; | ||
| 117 | enum AVColorSpace color_matrix; | ||
| 118 | |||
| 107 | int has_passthrough; /* apply pass through mode if possible */ | 119 | int has_passthrough; /* apply pass through mode if possible */ |
| 108 | int field_rate; /* Generate output at frame rate or field rate for deinterlace mode, 0: frame, 1: field */ | 120 | int field_rate; /* Generate output at frame rate or field rate for deinterlace mode, 0: frame, 1: field */ |
| 109 | } VPPContext; | 121 | } VPPContext; |
| @@ -231,6 +243,11 @@ static av_cold int vpp_preinit(AVFilterContext *ctx) · 121 unmodified lines | |||
| 231 | vpp->contrast = 1.0; | 243 | vpp->contrast = 1.0; |
| 232 | vpp->transpose = -1; | 244 | vpp->transpose = -1; |
| 233 | 245 | ||
| 246 | vpp->color_range = AVCOL_RANGE_UNSPECIFIED; | ||
| 247 | vpp->color_primaries = AVCOL_PRI_UNSPECIFIED; | ||
| 248 | vpp->color_transfer = AVCOL_TRC_UNSPECIFIED; | ||
| 249 | vpp->color_matrix = AVCOL_SPC_UNSPECIFIED; | ||
| 250 | |||
| 234 | vpp->has_passthrough = 1; | 251 | vpp->has_passthrough = 1; |
| 235 | 252 | ||
| 236 | return 0; | 253 | return 0; |
| @@ -250,6 +267,24 @@ static av_cold int vpp_init(AVFilterContext *ctx) · 13 unmodified lines | |||
| 250 | } | 267 | } |
| 251 | } | 268 | } |
| 252 | 269 | ||
| 270 | #define STRING_OPTION(var_name, func_name, default_value) do { \ | ||
| 271 | if (vpp->var_name ## _str) { \ | ||
| 272 | int var = av_ ## func_name ## _from_name(vpp->var_name ## _str); \ | ||
| 273 | if (var < 0) { \ | ||
| 274 | av_log(ctx, AV_LOG_ERROR, "Invalid %s.\n", #var_name); \ | ||
| 275 | return AVERROR(EINVAL); \ | ||
| 276 | } \ | ||
| 277 | vpp->var_name = var; \ | ||
| 278 | } else { \ | ||
| 279 | vpp->var_name = default_value; \ | ||
| 280 | } \ | ||
| 281 | } while (0) | ||
| 282 | |||
| 283 | STRING_OPTION(color_primaries, color_primaries, AVCOL_PRI_UNSPECIFIED); | ||
| 284 | STRING_OPTION(color_transfer, color_transfer, AVCOL_TRC_UNSPECIFIED); | ||
| 285 | STRING_OPTION(color_matrix, color_space, AVCOL_SPC_UNSPECIFIED); | ||
| 286 | |||
| 287 | #undef STRING_OPTION | ||
| 253 | return 0; | 288 | return 0; |
| 254 | } | 289 | } |
| 255 | 290 | ||
| @@ -353,11 +388,11 @@ static int vpp_set_frame_ext_params(AVFilterContext *ctx, const AVFrame *in, AVF · 97 unmodified lines | |||
| 353 | #if QSV_ONEVPL | 388 | #if QSV_ONEVPL |
| 354 | VPPContext *vpp = ctx->priv; | 389 | VPPContext *vpp = ctx->priv; |
| 355 | QSVVPPContext *qsvvpp = &vpp->qsv; | 390 | QSVVPPContext *qsvvpp = &vpp->qsv; |
| 356 | mfxExtVideoSignalInfo invsi_conf; | 391 | mfxExtVideoSignalInfo invsi_conf, outvsi_conf; |
| 357 | 392 | ||
| 358 | fp->num_ext_buf = 0; | 393 | fp->num_ext_buf = 0; |
| 359 | 394 | ||
| 360 | if (!in || | 395 | if (!in || !out || |
| 361 | !QSV_RUNTIME_VERSION_ATLEAST(qsvvpp->ver, 2, 0)) | 396 | !QSV_RUNTIME_VERSION_ATLEAST(qsvvpp->ver, 2, 0)) |
| 362 | return 0; | 397 | return 0; |
| 363 | 398 | ||
| @@ -370,9 +405,32 @@ static int vpp_set_frame_ext_params(AVFilterContext *ctx, const AVFrame *in, AVF · 6 unmodified lines | |||
| 370 | invsi_conf.MatrixCoefficients = (in->colorspace == AVCOL_SPC_UNSPECIFIED) ? AVCOL_SPC_BT709 : in->colorspace; | 405 | invsi_conf.MatrixCoefficients = (in->colorspace == AVCOL_SPC_UNSPECIFIED) ? AVCOL_SPC_BT709 : in->colorspace; |
| 371 | invsi_conf.ColourDescriptionPresent = 1; | 406 | invsi_conf.ColourDescriptionPresent = 1; |
| 372 | 407 | ||
| 373 | if (memcmp(&vpp->invsi_conf, &invsi_conf, sizeof(mfxExtVideoSignalInfo))) { | 408 | if (vpp->color_range != AVCOL_RANGE_UNSPECIFIED) |
| 409 | out->color_range = vpp->color_range; | ||
| 410 | if (vpp->color_primaries != AVCOL_PRI_UNSPECIFIED) | ||
| 411 | out->color_primaries = vpp->color_primaries; | ||
| 412 | if (vpp->color_transfer != AVCOL_TRC_UNSPECIFIED) | ||
| 413 | out->color_trc = vpp->color_transfer; | ||
| 414 | if (vpp->color_matrix != AVCOL_SPC_UNSPECIFIED) | ||
| 415 | out->colorspace = vpp->color_matrix; | ||
| 416 | |||
| 417 | memset(&outvsi_conf, 0, sizeof(mfxExtVideoSignalInfo)); | ||
| 418 | outvsi_conf.Header.BufferId = MFX_EXTBUFF_VIDEO_SIGNAL_INFO_OUT; | ||
| 419 | outvsi_conf.Header.BufferSz = sizeof(mfxExtVideoSignalInfo); | ||
| 420 | outvsi_conf.VideoFullRange = (out->color_range == AVCOL_RANGE_JPEG); | ||
| 421 | outvsi_conf.ColourPrimaries = (out->color_primaries == AVCOL_PRI_UNSPECIFIED) ? AVCOL_PRI_BT709 : out->color_primaries; | ||
| 422 | outvsi_conf.TransferCharacteristics = (out->color_trc == AVCOL_TRC_UNSPECIFIED) ? AVCOL_TRC_BT709 : out->color_trc; | ||
| 423 | outvsi_conf.MatrixCoefficients = (out->colorspace == AVCOL_SPC_UNSPECIFIED) ? AVCOL_SPC_BT709 : out->colorspace; | ||
| 424 | outvsi_conf.ColourDescriptionPresent = 1; | ||
| 425 | |||
| 426 | if (memcmp(&vpp->invsi_conf, &invsi_conf, sizeof(mfxExtVideoSignalInfo)) || | ||
| 427 | memcmp(&vpp->outvsi_conf, &outvsi_conf, sizeof(mfxExtVideoSignalInfo))) { | ||
| 374 | vpp->invsi_conf = invsi_conf; | 428 | vpp->invsi_conf = invsi_conf; |
| 375 | fp->ext_buf[fp->num_ext_buf++] = (mfxExtBuffer*)&vpp->invsi_conf; | 429 | fp->ext_buf[fp->num_ext_buf++] = (mfxExtBuffer*)&vpp->invsi_conf; |
| 430 | |||
| 431 | vpp->outvsi_conf = outvsi_conf; | ||
| 432 | fp->ext_buf[fp->num_ext_buf++] = (mfxExtBuffer*)&vpp->outvsi_conf; | ||
| 433 | |||
| 376 | } | 434 | } |
| 377 | #endif | 435 | #endif |
| 378 | 436 | ||
| @@ -560,6 +618,10 @@ static int config_output(AVFilterLink *outlink) · 181 unmodified lines | |||
| 560 | if (vpp->use_frc || vpp->use_crop || vpp->deinterlace || vpp->denoise || | 618 | if (vpp->use_frc || vpp->use_crop || vpp->deinterlace || vpp->denoise || |
| 561 | vpp->detail || vpp->procamp || vpp->rotate || vpp->hflip || | 619 | vpp->detail || vpp->procamp || vpp->rotate || vpp->hflip || |
| 562 | inlink->w != outlink->w || inlink->h != outlink->h || in_format != vpp->out_format || | 620 | inlink->w != outlink->w || inlink->h != outlink->h || in_format != vpp->out_format || |
| 621 | vpp->color_range != AVCOL_RANGE_UNSPECIFIED || | ||
| 622 | vpp->color_primaries != AVCOL_PRI_UNSPECIFIED || | ||
| 623 | vpp->color_transfer != AVCOL_TRC_UNSPECIFIED || | ||
| 624 | vpp->color_matrix != AVCOL_SPC_UNSPECIFIED || | ||
| 563 | !vpp->has_passthrough) | 625 | !vpp->has_passthrough) |
| 564 | return ff_qsvvpp_init(ctx, ¶m); | 626 | return ff_qsvvpp_init(ctx, ¶m); |
| 565 | else { | 627 | else { |
| @@ -750,6 +812,28 @@ static const AVOption vpp_options[] = { · 184 unmodified lines | |||
| 750 | { "field", "Output at field rate (one frame of output for each field)", | 812 | { "field", "Output at field rate (one frame of output for each field)", |
| 751 | 0, AV_OPT_TYPE_CONST, { .i64 = 1 }, 0, 0, FLAGS, "rate" }, | 813 | 0, AV_OPT_TYPE_CONST, { .i64 = 1 }, 0, 0, FLAGS, "rate" }, |
| 752 | 814 | ||
| 815 | { "out_range", "Output color range", | ||
| 816 | OFFSET(color_range), AV_OPT_TYPE_INT, { .i64 = AVCOL_RANGE_UNSPECIFIED }, | ||
| 817 | AVCOL_RANGE_UNSPECIFIED, AVCOL_RANGE_JPEG, FLAGS, "range" }, | ||
| 818 | { "full", "Full range", | ||
| 819 | 0, AV_OPT_TYPE_CONST, { .i64 = AVCOL_RANGE_JPEG }, 0, 0, FLAGS, "range" }, | ||
| 820 | { "limited", "Limited range", | ||
| 821 | 0, AV_OPT_TYPE_CONST, { .i64 = AVCOL_RANGE_MPEG }, 0, 0, FLAGS, "range" }, | ||
| 822 | { "jpeg", "Full range", | ||
| 823 | 0, AV_OPT_TYPE_CONST, { .i64 = AVCOL_RANGE_JPEG }, 0, 0, FLAGS, "range" }, | ||
| 824 | { "mpeg", "Limited range", | ||
| 825 | 0, AV_OPT_TYPE_CONST, { .i64 = AVCOL_RANGE_MPEG }, 0, 0, FLAGS, "range" }, | ||
| 826 | { "tv", "Limited range", | ||
| 827 | 0, AV_OPT_TYPE_CONST, { .i64 = AVCOL_RANGE_MPEG }, 0, 0, FLAGS, "range" }, | ||
| 828 | { "pc", "Full range", | ||
| 829 | 0, AV_OPT_TYPE_CONST, { .i64 = AVCOL_RANGE_JPEG }, 0, 0, FLAGS, "range" }, | ||
| 830 | { "out_color_matrix", "Output color matrix coefficient set", | ||
| 831 | OFFSET(color_matrix_str), AV_OPT_TYPE_STRING, { .str = NULL }, .flags = FLAGS }, | ||
| 832 | { "out_color_primaries", "Output color primaries", | ||
| 833 | OFFSET(color_primaries_str), AV_OPT_TYPE_STRING, { .str = NULL }, .flags = FLAGS }, | ||
| 834 | { "out_color_transfer", "Output color transfer characteristics", | ||
| 835 | OFFSET(color_transfer_str), AV_OPT_TYPE_STRING, { .str = NULL }, .flags = FLAGS }, | ||
| 836 | |||
| 753 | { NULL } | 837 | { NULL } |
| 754 | }; | 838 | }; |
| 755 | 839 | ||