option tonemap is added to disable / enable tonemapping. By default tonemapping is not performed.
Showing the changes to libavfilter (1 of 1 file). Show all
Unified · Split
| @@ -31,6 +31,7 @@ · 30 unmodified lines | ||
| 31 | 31 | #include "libavutil/hwcontext_qsv.h" |
| 32 | 32 | #include "libavutil/pixdesc.h" |
| 33 | 33 | #include "libavutil/mathematics.h" |
| 34 | +#include "libavutil/mastering_display_metadata.h" | |
| 34 | 35 | |
| 35 | 36 | #include "formats.h" |
| 36 | 37 | #include "internal.h" |
| @@ -63,6 +64,9 @@ typedef struct VPPContext{ · 26 unmodified lines | ||
| 63 | 64 | mfxExtVideoSignalInfo invsi_conf; |
| 64 | 65 | /** Video signal info attached on the output frame */ |
| 65 | 66 | mfxExtVideoSignalInfo outvsi_conf; |
| 67 | + /** HDR parameters attached on the input frame */ | |
| 68 | + mfxExtMasteringDisplayColourVolume mdcv_conf; | |
| 69 | + mfxExtContentLightLevelInfo clli_conf; | |
| 66 | 70 | #endif |
| 67 | 71 | |
| 68 | 72 | /** |
| @@ -118,6 +122,7 @@ typedef struct VPPContext{ · 49 unmodified lines | ||
| 118 | 122 | |
| 119 | 123 | int has_passthrough; /* apply pass through mode if possible */ |
| 120 | 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 | 126 | } VPPContext; |
| 122 | 127 | |
| 123 | 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 | 394 | VPPContext *vpp = ctx->priv; |
| 390 | 395 | QSVVPPContext *qsvvpp = &vpp->qsv; |
| 391 | 396 | mfxExtVideoSignalInfo invsi_conf, outvsi_conf; |
| 397 | + mfxExtMasteringDisplayColourVolume mdcv_conf; | |
| 398 | + mfxExtContentLightLevelInfo clli_conf; | |
| 399 | + AVFrameSideData *sd; | |
| 400 | + int tm = 0; | |
| 392 | 401 | |
| 393 | 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 | 414 | invsi_conf.MatrixCoefficients = (in->colorspace == AVCOL_SPC_UNSPECIFIED) ? AVCOL_SPC_BT709 : in->colorspace; |
| 406 | 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 | 484 | if (vpp->color_range != AVCOL_RANGE_UNSPECIFIED) |
| 409 | 485 | out->color_range = vpp->color_range; |
| 410 | 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 | 500 | outvsi_conf.ColourDescriptionPresent = 1; |
| 425 | 501 | |
| 426 | 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 | 505 | memcmp(&vpp->outvsi_conf, &outvsi_conf, sizeof(mfxExtVideoSignalInfo))) { |
| 428 | 506 | vpp->invsi_conf = invsi_conf; |
| 429 | 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 | 509 | vpp->outvsi_conf = outvsi_conf; |
| 432 | 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 | 520 | #endif |
| 436 | 521 | |
| @@ -622,6 +707,7 @@ static int config_output(AVFilterLink *outlink) · 185 unmodified lines | ||
| 622 | 707 | vpp->color_primaries != AVCOL_PRI_UNSPECIFIED || |
| 623 | 708 | vpp->color_transfer != AVCOL_TRC_UNSPECIFIED || |
| 624 | 709 | vpp->color_matrix != AVCOL_SPC_UNSPECIFIED || |
| 710 | + vpp->tonemap || | |
| 625 | 711 | !vpp->has_passthrough) |
| 626 | 712 | return ff_qsvvpp_init(ctx, ¶m); |
| 627 | 713 | else { |
| @@ -834,6 +920,8 @@ static const AVOption vpp_options[] = { · 206 unmodified lines | ||
| 834 | 920 | { "out_color_transfer", "Output color transfer characteristics", |
| 835 | 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 | 925 | { NULL } |
| 838 | 926 | }; |
| 839 | 927 | |