|
20 | 20 | #define __STDC_FORMAT_MACROS /* see inttypes.h */ |
21 | 21 | #include "common.h" |
22 | 22 | #include "mltdecklink_export.h" |
| 23 | +#include <algorithm> |
23 | 24 | #include <framework/mlt.h> |
24 | 25 | #include <limits.h> |
25 | 26 | #include <pthread.h> |
@@ -51,6 +52,18 @@ static const unsigned PREROLL_MINIMUM = 3; |
51 | 52 | enum { OP_NONE = 0, OP_OPEN, OP_START, OP_STOP, OP_EXIT }; |
52 | 53 | enum { EOTF_SDR = 0, EOTF_HDR = 1, EOTF_PQ = 2, EOTF_HLG = 3 }; ///< CEA 861.3 |
53 | 54 |
|
| 55 | +static double clamp_hdr_metadata(mlt_properties properties, |
| 56 | + const char *name, |
| 57 | + double defaultValue, |
| 58 | + double minimum, |
| 59 | + double maximum) |
| 60 | +{ |
| 61 | + double value = defaultValue; |
| 62 | + if (mlt_properties_get(properties, name)) |
| 63 | + value = mlt_properties_get_double(properties, name); |
| 64 | + return std::clamp(value, minimum, maximum); |
| 65 | +} |
| 66 | + |
54 | 67 | class DeckLinkConsumer : public IDeckLinkVideoOutputCallback, public IDeckLinkAudioOutputCallback |
55 | 68 | { |
56 | 69 | private: |
@@ -720,43 +733,70 @@ class DeckLinkConsumer : public IDeckLinkVideoOutputCallback, public IDeckLinkAu |
720 | 733 | frameMeta->SetInt(bmdDeckLinkFrameMetadataHDRElectroOpticalTransferFunc, |
721 | 734 | EOTF_PQ); |
722 | 735 | // CEA/SMPTE HDR metadata |
723 | | - // TODO: document and provide defaults for these |
| 736 | + const double hdrRedX |
| 737 | + = clamp_hdr_metadata(consumer_properties, "hdr_red_x", 0.7080, 0.0, 1.0); |
| 738 | + const double hdrRedY |
| 739 | + = clamp_hdr_metadata(consumer_properties, "hdr_red_y", 0.2920, 0.0, 1.0); |
| 740 | + const double hdrGreenX |
| 741 | + = clamp_hdr_metadata(consumer_properties, "hdr_green_x", 0.1700, 0.0, 1.0); |
| 742 | + const double hdrGreenY |
| 743 | + = clamp_hdr_metadata(consumer_properties, "hdr_green_y", 0.7970, 0.0, 1.0); |
| 744 | + const double hdrBlueX |
| 745 | + = clamp_hdr_metadata(consumer_properties, "hdr_blue_x", 0.1310, 0.0, 1.0); |
| 746 | + const double hdrBlueY |
| 747 | + = clamp_hdr_metadata(consumer_properties, "hdr_blue_y", 0.0460, 0.0, 1.0); |
| 748 | + const double hdrWhiteX |
| 749 | + = clamp_hdr_metadata(consumer_properties, "hdr_white_x", 0.3127, 0.0, 1.0); |
| 750 | + const double hdrWhiteY |
| 751 | + = clamp_hdr_metadata(consumer_properties, "hdr_white_y", 0.3290, 0.0, 1.0); |
| 752 | + const double hdrMaxLuminance = clamp_hdr_metadata(consumer_properties, |
| 753 | + "hdr_max_luminance", |
| 754 | + 1000.0, |
| 755 | + 1.0, |
| 756 | + 65535.0); |
| 757 | + const double hdrMinLuminance = clamp_hdr_metadata(consumer_properties, |
| 758 | + "hdr_min_luminance", |
| 759 | + 0.01, |
| 760 | + 0.0001, |
| 761 | + 6.5535); |
| 762 | + const double hdrMaxCll = clamp_hdr_metadata(consumer_properties, |
| 763 | + "hdr_max_cll", |
| 764 | + 1000.0, |
| 765 | + 1.0, |
| 766 | + 65535.0); |
| 767 | + const double hdrMaxFall = clamp_hdr_metadata(consumer_properties, |
| 768 | + "hdr_max_fall", |
| 769 | + 400.0, |
| 770 | + 1.0, |
| 771 | + 65535.0); |
724 | 772 | decklinkFrame->SetFlags(decklinkFrame->GetFlags() | bmdFrameContainsHDRMetadata); |
725 | | - frameMeta->SetFloat(bmdDeckLinkFrameMetadataHDRDisplayPrimariesRedX, |
726 | | - mlt_properties_get_double(consumer_properties, "hdr_red_x")); |
727 | | - frameMeta->SetFloat(bmdDeckLinkFrameMetadataHDRDisplayPrimariesRedY, |
728 | | - mlt_properties_get_double(consumer_properties, "hdr_red_y")); |
| 773 | + frameMeta->SetFloat(bmdDeckLinkFrameMetadataHDRDisplayPrimariesRedX, hdrRedX); |
| 774 | + frameMeta->SetFloat(bmdDeckLinkFrameMetadataHDRDisplayPrimariesRedY, hdrRedY); |
729 | 775 | frameMeta->SetFloat(bmdDeckLinkFrameMetadataHDRDisplayPrimariesGreenX, |
730 | | - mlt_properties_get_double(consumer_properties, |
731 | | - "hdr_green_x")); |
| 776 | + hdrGreenX); |
732 | 777 | frameMeta->SetFloat(bmdDeckLinkFrameMetadataHDRDisplayPrimariesGreenY, |
733 | | - mlt_properties_get_double(consumer_properties, |
734 | | - "hdr.green_y")); |
735 | | - frameMeta->SetFloat(bmdDeckLinkFrameMetadataHDRDisplayPrimariesBlueX, |
736 | | - mlt_properties_get_double(consumer_properties, |
737 | | - "hdr_blue_x")); |
738 | | - frameMeta->SetFloat(bmdDeckLinkFrameMetadataHDRDisplayPrimariesBlueY, |
739 | | - mlt_properties_get_double(consumer_properties, |
740 | | - "hdr_blue_y")); |
741 | | - frameMeta->SetFloat(bmdDeckLinkFrameMetadataHDRWhitePointX, |
742 | | - mlt_properties_get_double(consumer_properties, |
743 | | - "hdr_white_x")); |
744 | | - frameMeta->SetFloat(bmdDeckLinkFrameMetadataHDRWhitePointY, |
745 | | - mlt_properties_get_double(consumer_properties, |
746 | | - "hdr_white_y")); |
| 778 | + hdrGreenY); |
| 779 | + frameMeta->SetFloat(bmdDeckLinkFrameMetadataHDRDisplayPrimariesBlueX, hdrBlueX); |
| 780 | + frameMeta->SetFloat(bmdDeckLinkFrameMetadataHDRDisplayPrimariesBlueY, hdrBlueY); |
| 781 | + frameMeta->SetFloat(bmdDeckLinkFrameMetadataHDRWhitePointX, hdrWhiteX); |
| 782 | + frameMeta->SetFloat(bmdDeckLinkFrameMetadataHDRWhitePointY, hdrWhiteY); |
747 | 783 | frameMeta->SetFloat(bmdDeckLinkFrameMetadataHDRMaxDisplayMasteringLuminance, |
748 | | - mlt_properties_get_double(consumer_properties, |
749 | | - "hdr_max_luminance")); |
| 784 | + hdrMaxLuminance); |
750 | 785 | frameMeta->SetFloat(bmdDeckLinkFrameMetadataHDRMinDisplayMasteringLuminance, |
751 | | - mlt_properties_get_double(consumer_properties, |
752 | | - "hdr_min_luminance")); |
| 786 | + hdrMinLuminance); |
753 | 787 | frameMeta->SetFloat(bmdDeckLinkFrameMetadataHDRMaximumContentLightLevel, |
754 | | - mlt_properties_get_double(consumer_properties, |
755 | | - "hdr_max_cll")); |
| 788 | + hdrMaxCll); |
756 | 789 | frameMeta->SetFloat(bmdDeckLinkFrameMetadataHDRMaximumFrameAverageLightLevel, |
757 | | - mlt_properties_get_double(consumer_properties, |
758 | | - "hdr_max_fall")); |
| 790 | + hdrMaxFall); |
| 791 | + } else { |
| 792 | + // Frames are reused from a pool, so explicitly clear any stale HDR transfer |
| 793 | + // and static metadata flag left behind by prior PQ/HLG output. |
| 794 | + frameMeta->SetInt(bmdDeckLinkFrameMetadataHDRElectroOpticalTransferFunc, |
| 795 | + EOTF_SDR); |
| 796 | + decklinkFrame->SetFlags(decklinkFrame->GetFlags() |
| 797 | + & ~bmdFrameContainsHDRMetadata); |
759 | 798 | } |
| 799 | + frameMeta->Release(); |
760 | 800 | } else { |
761 | 801 | mlt_log_debug(getConsumer(), |
762 | 802 | "Unable to get IDeckLinkVideoFrameMutableMetadataExtensions\n"); |
|
0 commit comments