From 24ee9f8cf3736c5cd946eb6df8bd3189f8a62ce0 Mon Sep 17 00:00:00 2001 From: Carl Hetherington Date: Tue, 14 Oct 2025 21:14:04 +0200 Subject: Fix MPEG2 DCP gamma (#3026). --- src/lib/colour_conversion.cc | 14 ++++++++++++++ src/lib/mpeg2_encoder.cc | 20 +++++++++++++++++++- 2 files changed, 33 insertions(+), 1 deletion(-) (limited to 'src/lib') diff --git a/src/lib/colour_conversion.cc b/src/lib/colour_conversion.cc index b5d6cd4c5..5dc633f60 100644 --- a/src/lib/colour_conversion.cc +++ b/src/lib/colour_conversion.cc @@ -138,6 +138,12 @@ ColourConversion::ColourConversion(cxml::NodePtr node, int version) } else { _out_j2k = make_shared(); } + + if (auto mpeg2_gamma = node->optional_number_child("OutputMPEG2Gamma")) { + _out_mpeg2 = make_shared(*mpeg2_gamma); + } else { + _out_mpeg2 = make_shared(); + } } boost::optional @@ -186,6 +192,10 @@ ColourConversion::as_xml(xmlpp::Element* element) const if (auto gf = dynamic_pointer_cast(_out_j2k)) { cxml::add_text_child(element, "OutputGamma", fmt::to_string(gf->gamma())); } + + if (auto gf = dynamic_pointer_cast(_out_mpeg2)) { + cxml::add_text_child(element, "OutputMPEG2Gamma", fmt::to_string(gf->gamma())); + } } optional @@ -240,6 +250,10 @@ ColourConversion::identifier() const digester.add(gf->gamma()); } + if (auto gf = dynamic_pointer_cast(_out_mpeg2)) { + digester.add(gf->gamma()); + } + return digester.get(); } diff --git a/src/lib/mpeg2_encoder.cc b/src/lib/mpeg2_encoder.cc index 38388431d..c9ee6c491 100644 --- a/src/lib/mpeg2_encoder.cc +++ b/src/lib/mpeg2_encoder.cc @@ -22,6 +22,7 @@ #include "mpeg2_encoder.h" #include "writer.h" #include +#include extern "C" { #include } @@ -43,7 +44,24 @@ MPEG2Encoder::encode(shared_ptr pv, dcpomatic::DCPTime time) { VideoEncoder::encode(pv, time); - auto image = pv->image(force(AV_PIX_FMT_YUV420P), VideoRange::VIDEO, false); + shared_ptr image; + + if (auto conversion = pv->colour_conversion()) { + if (!conversion->in()->about_equal(conversion->out_mpeg2(), 0.05)) { + image = pv->image([](AVPixelFormat) { return AV_PIX_FMT_RGB24; }, VideoRange::VIDEO, Image::Alignment::PADDED, false); + dcp::convert_rgb_gamma(image->data()[0], image->size(), image->stride()[0], *conversion); + image = image->convert_pixel_format(conversion->yuv_to_rgb(), AV_PIX_FMT_YUV420P, Image::Alignment::COMPACT, false); + } + } + + if (!image) { + image = pv->image( + [](AVPixelFormat) { return AV_PIX_FMT_YUV420P; }, + VideoRange::VIDEO, + Image::Alignment::COMPACT, + false + ); + } dcp::FFmpegImage ffmpeg_image(time.get() * _film->video_frame_rate() / dcpomatic::DCPTime::HZ); -- cgit v1.2.3