summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCarl Hetherington <cth@carlh.net>2025-10-14 21:14:04 +0200
committerCarl Hetherington <cth@carlh.net>2025-10-14 21:14:22 +0200
commit24ee9f8cf3736c5cd946eb6df8bd3189f8a62ce0 (patch)
treed33e33ded5b766cff09d748786a8427949de1f1d
parent1f336350e4c6f60c4597b43976d1a9e4e05ea61b (diff)
Fix MPEG2 DCP gamma (#3026).3026-mpeg2-colour
-rw-r--r--src/lib/colour_conversion.cc14
-rw-r--r--src/lib/mpeg2_encoder.cc20
-rw-r--r--src/wx/colour_conversion_editor.cc12
-rw-r--r--src/wx/colour_conversion_editor.h1
-rw-r--r--test/colour_conversion_test.cc2
5 files changed, 48 insertions, 1 deletions
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<dcp::IdentityTransferFunction>();
}
+
+ if (auto mpeg2_gamma = node->optional_number_child<double>("OutputMPEG2Gamma")) {
+ _out_mpeg2 = make_shared<dcp::GammaTransferFunction>(*mpeg2_gamma);
+ } else {
+ _out_mpeg2 = make_shared<dcp::IdentityTransferFunction>();
+ }
}
boost::optional<ColourConversion>
@@ -186,6 +192,10 @@ ColourConversion::as_xml(xmlpp::Element* element) const
if (auto gf = dynamic_pointer_cast<const dcp::GammaTransferFunction>(_out_j2k)) {
cxml::add_text_child(element, "OutputGamma", fmt::to_string(gf->gamma()));
}
+
+ if (auto gf = dynamic_pointer_cast<const dcp::GammaTransferFunction>(_out_mpeg2)) {
+ cxml::add_text_child(element, "OutputMPEG2Gamma", fmt::to_string(gf->gamma()));
+ }
}
optional<size_t>
@@ -240,6 +250,10 @@ ColourConversion::identifier() const
digester.add(gf->gamma());
}
+ if (auto gf = dynamic_pointer_cast<const dcp::GammaTransferFunction>(_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 <dcp/ffmpeg_image.h>
+#include <dcp/transfer_function.h>
extern "C" {
#include <libavutil/pixfmt.h>
}
@@ -43,7 +44,24 @@ MPEG2Encoder::encode(shared_ptr<PlayerVideo> pv, dcpomatic::DCPTime time)
{
VideoEncoder::encode(pv, time);
- auto image = pv->image(force(AV_PIX_FMT_YUV420P), VideoRange::VIDEO, false);
+ shared_ptr<Image> 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);
diff --git a/src/wx/colour_conversion_editor.cc b/src/wx/colour_conversion_editor.cc
index a16b7066f..83dbf67b7 100644
--- a/src/wx/colour_conversion_editor.cc
+++ b/src/wx/colour_conversion_editor.cc
@@ -216,6 +216,10 @@ ColourConversionEditor::ColourConversionEditor (wxWindow* parent, bool yuv)
table->Add(_output_j2k, wxGBPosition(r, 0), wxGBSpan(1, 2));
++r;
+ _output_mpeg2 = new CheckBox(this, _("Inverse 2.4 gamma correction on output to MPEG2"));
+ table->Add(_output_mpeg2, wxGBPosition(r, 0), wxGBSpan(1, 2));
+ ++r;
+
_input_gamma->SetRange (0.1, 4.0);
_input_gamma->SetDigits (2);
_input_gamma->SetIncrement (0.1);
@@ -242,6 +246,7 @@ ColourConversionEditor::ColourConversionEditor (wxWindow* parent, bool yuv)
_adjusted_white_y->Bind (wxEVT_TEXT, bind (&ColourConversionEditor::adjusted_white_changed, this));
_yuv_to_rgb->Bind (wxEVT_CHOICE, bind (&ColourConversionEditor::changed, this));
_output_j2k->bind(&ColourConversionEditor::changed, this);
+ _output_mpeg2->bind(&ColourConversionEditor::changed, this);
}
@@ -313,6 +318,7 @@ ColourConversionEditor::set (ColourConversion conversion)
}
_output_j2k->SetValue(static_cast<bool>(dynamic_pointer_cast<const dcp::GammaTransferFunction>(conversion.out_j2k())));
+ _output_mpeg2->SetValue(static_cast<bool>(dynamic_pointer_cast<const dcp::GammaTransferFunction>(conversion.out_mpeg2())));
update_rgb_to_xyz ();
update_bradford ();
@@ -380,6 +386,12 @@ ColourConversionEditor::get () const
conversion.set_out_j2k(make_shared<dcp::IdentityTransferFunction>());
}
+ if (_output_mpeg2->GetValue()) {
+ conversion.set_out_mpeg2(make_shared<dcp::GammaTransferFunction>(2.4));
+ } else {
+ conversion.set_out_mpeg2(make_shared<dcp::IdentityTransferFunction>());
+ }
+
return conversion;
}
diff --git a/src/wx/colour_conversion_editor.h b/src/wx/colour_conversion_editor.h
index ac2273540..6ec524992 100644
--- a/src/wx/colour_conversion_editor.h
+++ b/src/wx/colour_conversion_editor.h
@@ -83,6 +83,7 @@ private:
wxTextCtrl* _adjusted_white_x;
wxTextCtrl* _adjusted_white_y;
CheckBox* _output_j2k;
+ CheckBox* _output_mpeg2;
wxStaticText* _rgb_to_xyz[3][3];
wxStaticText* _bradford[3][3];
};
diff --git a/test/colour_conversion_test.cc b/test/colour_conversion_test.cc
index db33a2b37..765ad491a 100644
--- a/test/colour_conversion_test.cc
+++ b/test/colour_conversion_test.cc
@@ -74,6 +74,7 @@ BOOST_AUTO_TEST_CASE (colour_conversion_test2)
" <WhiteX>0.3127</WhiteX>\n"
" <WhiteY>0.329</WhiteY>\n"
" <OutputGamma>2.6</OutputGamma>\n"
+ " <OutputMPEG2Gamma>2.4</OutputMPEG2Gamma>\n"
"</Test>\n"
);
}
@@ -103,6 +104,7 @@ BOOST_AUTO_TEST_CASE (colour_conversion_test3)
" <WhiteX>0.3127</WhiteX>\n"
" <WhiteY>0.329</WhiteY>\n"
" <OutputGamma>2.6</OutputGamma>\n"
+ " <OutputMPEG2Gamma>2.4</OutputMPEG2Gamma>\n"
"</Test>\n"
);
}