option tonemap is added to disable / enable tonemapping. By default tonemapping is not performed.
Unified · Split
| @@ -31,6 +31,7 @@ · 30 unmodified lines | |||
| 31 | #include "libavutil/hwcontext_qsv.h" | 31 | #include "libavutil/hwcontext_qsv.h" |
| 32 | #include "libavutil/pixdesc.h" | 32 | #include "libavutil/pixdesc.h" |
| 33 | #include "libavutil/mathematics.h" | 33 | #include "libavutil/mathematics.h" |
| 34 | #include "libavutil/mastering_display_metadata.h" | ||
| 34 | 35 | ||
| 35 | #include "formats.h" | 36 | #include "formats.h" |
| 36 | #include "internal.h" | 37 | #include "internal.h" |
| @@ -63,6 +64,9 @@ typedef struct VPPContext{ · 26 unmodified lines | |||
| 63 | mfxExtVideoSignalInfo invsi_conf; | 64 | mfxExtVideoSignalInfo invsi_conf; |
| 64 | /** Video signal info attached on the output frame */ | 65 | /** Video signal info attached on the output frame */ |
| 65 | mfxExtVideoSignalInfo outvsi_conf; | 66 | mfxExtVideoSignalInfo outvsi_conf; |
| 67 | /** HDR parameters attached on the input frame */ | ||
| 68 | mfxExtMasteringDisplayColourVolume mdcv_conf; | ||
| 69 | mfxExtContentLightLevelInfo clli_conf; | ||
| 66 | #endif | 70 | #endif |
| 67 | 71 | ||
| 68 | /** | 72 | /** |
| @@ -118,6 +122,7 @@ typedef struct VPPContext{ · 49 unmodified lines | |||
| 118 | 122 | ||
| 119 | int has_passthrough; /* apply pass through mode if possible */ | 123 | int has_passthrough; /* apply pass through mode if possible */ |
| 120 | int field_rate; /* Generate output at frame rate or field rate for deinterlace mode, 0: frame, 1: field */ | 124 | int field_rate; /* Generate output at frame rate or field rate for deinterlace mode, 0: frame, 1: field */ |
| 125 | int tonemap; /* 1: perform tonemapping if the input has HDR metadata, 0: always disable tonemapping */ | ||
| 121 | } VPPContext; | 126 | } VPPContext; |
| 122 | 127 | ||
| 123 | static const char *const var_names[] = { | 128 | static const char *const var_names[] = { |
| @@ -389,6 +394,10 @@ static int vpp_set_frame_ext_params(AVFilterContext *ctx, const AVFrame *in, AVF · 265 unmodified lines | |||
| 389 | VPPContext *vpp = ctx->priv; | 394 | VPPContext *vpp = ctx->priv; |
| 390 | QSVVPPContext *qsvvpp = &vpp->qsv; | 395 | QSVVPPContext *qsvvpp = &vpp->qsv; |
| 391 | mfxExtVideoSignalInfo invsi_conf, outvsi_conf; | 396 | mfxExtVideoSignalInfo invsi_conf, outvsi_conf; |
| 397 | mfxExtMasteringDisplayColourVolume mdcv_conf; | ||
| 398 | mfxExtContentLightLevelInfo clli_conf; | ||
| 399 | AVFrameSideData *sd; | ||
| 400 | int tm = 0; | ||
| 392 | 401 | ||
| 393 | fp->num_ext_buf = 0; | 402 | fp->num_ext_buf = 0; |
| 394 | 403 | ||
| @@ -405,6 +414,73 @@ static int vpp_set_frame_ext_params(AVFilterContext *ctx, const AVFrame *in, AVF · 10 unmodified lines | |||
| 405 | invsi_conf.MatrixCoefficients = (in->colorspace == AVCOL_SPC_UNSPECIFIED) ? AVCOL_SPC_BT709 : in->colorspace; | 414 | invsi_conf.MatrixCoefficients = (in->colorspace == AVCOL_SPC_UNSPECIFIED) ? AVCOL_SPC_BT709 : in->colorspace; |
| 406 | invsi_conf.ColourDescriptionPresent = 1; | 415 | invsi_conf.ColourDescriptionPresent = 1; |
| 407 | 416 | ||
| 417 | memset(&mdcv_conf, 0, sizeof(mfxExtMasteringDisplayColourVolume)); | ||
| 418 | sd = av_frame_get_side_data(in, AV_FRAME_DATA_MASTERING_DISPLAY_METADATA); | ||
| 419 | if (vpp->tonemap && sd) { | ||
| 420 | AVMasteringDisplayMetadata *mdm = (AVMasteringDisplayMetadata *)sd->data; | ||
| 421 | |||
| 422 | if (mdm->has_primaries && mdm->has_luminance) { | ||
| 423 | const int mapping[3] = {1, 2, 0}; | ||
| 424 | const int chroma_den = 50000; | ||
| 425 | const int luma_den = 10000; | ||
| 426 | int i; | ||
| 427 | |||
| 428 | mdcv_conf.Header.BufferId = MFX_EXTBUFF_MASTERING_DISPLAY_COLOUR_VOLUME_IN; | ||
| 429 | mdcv_conf.Header.BufferSz = sizeof(mfxExtMasteringDisplayColourVolume); | ||
| 430 | |||
| 431 | for (i = 0; i < 3; i++) { | ||
| 432 | const int j = mapping[i]; | ||
| 433 | |||
| 434 | mdcv_conf.DisplayPrimariesX[i] = | ||
| 435 | FFMIN(lrint(chroma_den * | ||
| 436 | av_q2d(mdm->display_primaries[j][0])), | ||
| 437 | chroma_den); | ||
| 438 | mdcv_conf.DisplayPrimariesY[i] = | ||
| 439 | FFMIN(lrint(chroma_den * | ||
| 440 | av_q2d(mdm->display_primaries[j][1])), | ||
| 441 | chroma_den); | ||
| 442 | } | ||
| 443 | |||
| 444 | mdcv_conf.WhitePointX = | ||
| 445 | FFMIN(lrint(chroma_den * av_q2d(mdm->white_point[0])), | ||
| 446 | chroma_den); | ||
| 447 | mdcv_conf.WhitePointY = | ||
| 448 | FFMIN(lrint(chroma_den * av_q2d(mdm->white_point[1])), | ||
| 449 | chroma_den); | ||
| 450 | |||
| 451 | /* MaxDisplayMasteringLuminance is in the unit of 1 nits however | ||
| 452 | * MinDisplayMasteringLuminance is in the unit of 0.0001 nits | ||
| 453 | */ | ||
| 454 | mdcv_conf.MaxDisplayMasteringLuminance = | ||
| 455 | lrint(av_q2d(mdm->max_luminance)); | ||
| 456 | mdcv_conf.MinDisplayMasteringLuminance = | ||
| 457 | lrint(luma_den * av_q2d(mdm->min_luminance)); | ||
| 458 | tm = 1; | ||
| 459 | } | ||
| 460 | } | ||
| 461 | |||
| 462 | memset(&clli_conf, 0, sizeof(mfxExtContentLightLevelInfo)); | ||
| 463 | sd = av_frame_get_side_data(in, AV_FRAME_DATA_CONTENT_LIGHT_LEVEL); | ||
| 464 | if (vpp->tonemap && sd) { | ||
| 465 | AVContentLightMetadata *clm = (AVContentLightMetadata *)sd->data; | ||
| 466 | |||
| 467 | clli_conf.Header.BufferId = MFX_EXTBUFF_CONTENT_LIGHT_LEVEL_INFO; | ||
| 468 | clli_conf.Header.BufferSz = sizeof(mfxExtContentLightLevelInfo); | ||
| 469 | clli_conf.MaxContentLightLevel = FFMIN(clm->MaxCLL, 65535); | ||
| 470 | clli_conf.MaxPicAverageLightLevel = FFMIN(clm->MaxFALL, 65535); | ||
| 471 | tm = 1; | ||
| 472 | } | ||
| 473 | |||
| 474 | if (tm) { | ||
| 475 | av_frame_remove_side_data(out, AV_FRAME_DATA_CONTENT_LIGHT_LEVEL); | ||
| 476 | av_frame_remove_side_data(out, AV_FRAME_DATA_MASTERING_DISPLAY_METADATA); | ||
| 477 | |||
| 478 | out->color_primaries = AVCOL_PRI_BT709; | ||
| 479 | out->color_trc = AVCOL_TRC_BT709; | ||
| 480 | out->colorspace = AVCOL_SPC_BT709; | ||
| 481 | out->color_range = AVCOL_RANGE_MPEG; | ||
| 482 | } | ||
| 483 | |||
| 408 | if (vpp->color_range != AVCOL_RANGE_UNSPECIFIED) | 484 | if (vpp->color_range != AVCOL_RANGE_UNSPECIFIED) |
| 409 | out->color_range = vpp->color_range; | 485 | out->color_range = vpp->color_range; |
| 410 | if (vpp->color_primaries != AVCOL_PRI_UNSPECIFIED) | 486 | if (vpp->color_primaries != AVCOL_PRI_UNSPECIFIED) |
| @@ -424,6 +500,8 @@ static int vpp_set_frame_ext_params(AVFilterContext *ctx, const AVFrame *in, AVF · 13 unmodified lines | |||
| 424 | outvsi_conf.ColourDescriptionPresent = 1; | 500 | outvsi_conf.ColourDescriptionPresent = 1; |
| 425 | 501 | ||
| 426 | if (memcmp(&vpp->invsi_conf, &invsi_conf, sizeof(mfxExtVideoSignalInfo)) || | 502 | if (memcmp(&vpp->invsi_conf, &invsi_conf, sizeof(mfxExtVideoSignalInfo)) || |
| 503 | memcmp(&vpp->mdcv_conf, &mdcv_conf, sizeof(mfxExtMasteringDisplayColourVolume)) || | ||
| 504 | memcmp(&vpp->clli_conf, &clli_conf, sizeof(mfxExtContentLightLevelInfo)) || | ||
| 427 | memcmp(&vpp->outvsi_conf, &outvsi_conf, sizeof(mfxExtVideoSignalInfo))) { | 505 | memcmp(&vpp->outvsi_conf, &outvsi_conf, sizeof(mfxExtVideoSignalInfo))) { |
| 428 | vpp->invsi_conf = invsi_conf; | 506 | vpp->invsi_conf = invsi_conf; |
| 429 | fp->ext_buf[fp->num_ext_buf++] = (mfxExtBuffer*)&vpp->invsi_conf; | 507 | fp->ext_buf[fp->num_ext_buf++] = (mfxExtBuffer*)&vpp->invsi_conf; |
| @@ -431,6 +509,13 @@ static int vpp_set_frame_ext_params(AVFilterContext *ctx, const AVFrame *in, AVF · 1 unmodified line | |||
| 431 | vpp->outvsi_conf = outvsi_conf; | 509 | vpp->outvsi_conf = outvsi_conf; |
| 432 | fp->ext_buf[fp->num_ext_buf++] = (mfxExtBuffer*)&vpp->outvsi_conf; | 510 | fp->ext_buf[fp->num_ext_buf++] = (mfxExtBuffer*)&vpp->outvsi_conf; |
| 433 | 511 | ||
| 512 | vpp->mdcv_conf = mdcv_conf; | ||
| 513 | if (mdcv_conf.Header.BufferId) | ||
| 514 | fp->ext_buf[fp->num_ext_buf++] = (mfxExtBuffer*)&vpp->mdcv_conf; | ||
| 515 | |||
| 516 | vpp->clli_conf = clli_conf; | ||
| 517 | if (clli_conf.Header.BufferId) | ||
| 518 | fp->ext_buf[fp->num_ext_buf++] = (mfxExtBuffer*)&vpp->clli_conf; | ||
| 434 | } | 519 | } |
| 435 | #endif | 520 | #endif |
| 436 | 521 | ||
| @@ -622,6 +707,7 @@ static int config_output(AVFilterLink *outlink) · 185 unmodified lines | |||
| 622 | vpp->color_primaries != AVCOL_PRI_UNSPECIFIED || | 707 | vpp->color_primaries != AVCOL_PRI_UNSPECIFIED || |
| 623 | vpp->color_transfer != AVCOL_TRC_UNSPECIFIED || | 708 | vpp->color_transfer != AVCOL_TRC_UNSPECIFIED || |
| 624 | vpp->color_matrix != AVCOL_SPC_UNSPECIFIED || | 709 | vpp->color_matrix != AVCOL_SPC_UNSPECIFIED || |
| 710 | vpp->tonemap || | ||
| 625 | !vpp->has_passthrough) | 711 | !vpp->has_passthrough) |
| 626 | return ff_qsvvpp_init(ctx, ¶m); | 712 | return ff_qsvvpp_init(ctx, ¶m); |
| 627 | else { | 713 | else { |
| @@ -834,6 +920,8 @@ static const AVOption vpp_options[] = { · 206 unmodified lines | |||
| 834 | { "out_color_transfer", "Output color transfer characteristics", | 920 | { "out_color_transfer", "Output color transfer characteristics", |
| 835 | OFFSET(color_transfer_str), AV_OPT_TYPE_STRING, { .str = NULL }, .flags = FLAGS }, | 921 | OFFSET(color_transfer_str), AV_OPT_TYPE_STRING, { .str = NULL }, .flags = FLAGS }, |
| 836 | 922 | ||
| 923 | {"tonemap", "Perform tonemapping (0=disable tonemapping, 1=perform tonemapping if the input has HDR metadata)", OFFSET(tonemap), AV_OPT_TYPE_INT, {.i64 = 0 }, 0, 1, .flags = FLAGS}, | ||
| 924 | |||
| 837 | { NULL } | 925 | { NULL } |
| 838 | }; | 926 | }; |
| 839 | 927 | ||