Skip to content

Commit

Permalink
rdd36: improve descriptor property guesses based on colorimetry
Browse files Browse the repository at this point in the history
Allow matching any value for color primaries, transfer characteristic or
matric coefficients to avoid enumerating all combinations.

Check that the colorimetry is BT709 for a 274M or 296M signal standard.
If not then set the signal standard to "none".
  • Loading branch information
philipnbbc committed Sep 5, 2023
1 parent a9866f0 commit eb4df19
Show file tree
Hide file tree
Showing 4 changed files with 162 additions and 54 deletions.
137 changes: 90 additions & 47 deletions src/mxf_helper/RDD36MXFDescriptorHelper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -50,54 +50,44 @@ typedef struct
uint32_t width;
uint32_t height;
bool is_full_frame;
mxfUL color_primaries;
mxfUL transfer_characteristic;
mxfUL matrix_coefficients;
mxfUL color_primaries[2];
mxfUL transfer_characteristic[4];
mxfUL matrix_coefficients[2];

// guesses
uint8_t signal_standard;
uint8_t signal_standard; // Can be changed to "none" if the colorimetry values don't match
Rational aspect_ratio;
mxfVideoLineMap video_line_map;
uint8_t color_siting;
} DefaultParameterMatch;

// TODO: add more defaults
// TODO: are the SD NTSC video line numbers correct?
// TODO: add more guesses
static const DefaultParameterMatch DEFAULT_PARAM_MATCHES[] =
{
{720, 480, false, SMPTE170M_COLOR_PRIM, ITUR_BT709_TRANSFER_CH, ITUR_BT601_CODING_EQ,
{720, 480, false,
{SMPTE170M_COLOR_PRIM, ITUR_BT470_TRANSFER_CH},
{ITUR_BT709_TRANSFER_CH, g_Null_UL, g_Null_UL, g_Null_UL},
{ITUR_BT601_CODING_EQ, g_Null_UL},
MXF_SIGNAL_STANDARD_ITU601, {16, 9}, {23, 285}, MXF_COLOR_SITING_COSITING},
{720, 576, false, ITUR_BT470_TRANSFER_CH, ITUR_BT709_TRANSFER_CH, ITUR_BT601_CODING_EQ,
MXF_SIGNAL_STANDARD_ITU601, {16, 9}, {23, 336}, MXF_COLOR_SITING_COSITING},
{1280, 720, true, ITU709_COLOR_PRIM, ITUR_BT709_TRANSFER_CH, ITUR_BT709_CODING_EQ,
MXF_SIGNAL_STANDARD_SMPTE296M, {16, 9}, {26, 0}, MXF_COLOR_SITING_COSITING},
{1280, 720, true, ITU2020_COLOR_PRIM, ITU2020_TRANSFER_CH, ITU2020_NCL_CODING_EQ,
MXF_SIGNAL_STANDARD_SMPTE296M, {16, 9}, {26, 0}, MXF_COLOR_SITING_COSITING},
{1280, 720, true, ITU2020_COLOR_PRIM, SMPTE_ST2084_TRANSFER_CH, ITU2020_NCL_CODING_EQ,
MXF_SIGNAL_STANDARD_SMPTE296M, {16, 9}, {26, 0}, MXF_COLOR_SITING_COSITING},
{1280, 720, true, ITU2020_COLOR_PRIM, HLG_OETF_TRANSFER_CH, ITU2020_NCL_CODING_EQ,
MXF_SIGNAL_STANDARD_SMPTE296M, {16, 9}, {26, 0}, MXF_COLOR_SITING_COSITING},
{1920, 1080, false, ITU709_COLOR_PRIM, ITUR_BT709_TRANSFER_CH, ITUR_BT709_CODING_EQ,
MXF_SIGNAL_STANDARD_SMPTE274M, {16, 9}, {21, 584}, MXF_COLOR_SITING_COSITING},
{1920, 1080, false, ITU2020_COLOR_PRIM, ITU2020_TRANSFER_CH, ITU2020_NCL_CODING_EQ,
MXF_SIGNAL_STANDARD_SMPTE274M, {16, 9}, {21, 584}, MXF_COLOR_SITING_COSITING},
{1920, 1080, false, ITU2020_COLOR_PRIM, SMPTE_ST2084_TRANSFER_CH, ITU2020_NCL_CODING_EQ,
MXF_SIGNAL_STANDARD_SMPTE274M, {16, 9}, {21, 584}, MXF_COLOR_SITING_COSITING},
{1920, 1080, false, ITU2020_COLOR_PRIM, HLG_OETF_TRANSFER_CH, ITU2020_NCL_CODING_EQ,
MXF_SIGNAL_STANDARD_SMPTE274M, {16, 9}, {21, 584}, MXF_COLOR_SITING_COSITING},
{1920, 1080, true, ITU709_COLOR_PRIM, ITUR_BT709_TRANSFER_CH, ITUR_BT709_CODING_EQ,
MXF_SIGNAL_STANDARD_SMPTE274M, {16, 9}, {42, 0}, MXF_COLOR_SITING_COSITING},
{1920, 1080, true, ITU2020_COLOR_PRIM, ITU2020_TRANSFER_CH, ITU2020_NCL_CODING_EQ,
MXF_SIGNAL_STANDARD_SMPTE274M, {16, 9}, {42, 0}, MXF_COLOR_SITING_COSITING},
{1920, 1080, true, ITU2020_COLOR_PRIM, SMPTE_ST2084_TRANSFER_CH, ITU2020_NCL_CODING_EQ,
MXF_SIGNAL_STANDARD_SMPTE274M, {16, 9}, {42, 0}, MXF_COLOR_SITING_COSITING},
{1920, 1080, true, ITU2020_COLOR_PRIM, HLG_OETF_TRANSFER_CH, ITU2020_NCL_CODING_EQ,
MXF_SIGNAL_STANDARD_SMPTE274M, {16, 9}, {42, 0}, MXF_COLOR_SITING_COSITING},
{3840, 2160, false, ITU2020_COLOR_PRIM, ITU2020_TRANSFER_CH, ITU2020_NCL_CODING_EQ,
MXF_SIGNAL_STANDARD_NONE, {16, 9}, {1, 0}, MXF_COLOR_SITING_COSITING},
{3840, 2160, false, ITU2020_COLOR_PRIM, SMPTE_ST2084_TRANSFER_CH, ITU2020_NCL_CODING_EQ,
MXF_SIGNAL_STANDARD_NONE, {16, 9}, {1, 0}, MXF_COLOR_SITING_COSITING},
{3840, 2160, false, ITU2020_COLOR_PRIM, HLG_OETF_TRANSFER_CH, ITU2020_NCL_CODING_EQ,
{1280, 720, true,
{ITU709_COLOR_PRIM, ITU2020_COLOR_PRIM},
{ITUR_BT709_TRANSFER_CH, ITU2020_TRANSFER_CH, SMPTE_ST2084_TRANSFER_CH, HLG_OETF_TRANSFER_CH},
{ITUR_BT709_CODING_EQ, ITU2020_NCL_CODING_EQ},
MXF_SIGNAL_STANDARD_SMPTE296M /* or None */, {16, 9}, {26, 0}, MXF_COLOR_SITING_COSITING},
{1920, 1080, false,
{ITU709_COLOR_PRIM, ITU2020_COLOR_PRIM},
{ITUR_BT709_TRANSFER_CH,ITU2020_TRANSFER_CH, SMPTE_ST2084_TRANSFER_CH, HLG_OETF_TRANSFER_CH},
{ITUR_BT709_CODING_EQ, ITU2020_NCL_CODING_EQ},
MXF_SIGNAL_STANDARD_SMPTE274M /* or None */, {16, 9}, {21, 584}, MXF_COLOR_SITING_COSITING},
{1920, 1080, true,
{ITU709_COLOR_PRIM, ITU2020_COLOR_PRIM},
{ITUR_BT709_TRANSFER_CH, ITU2020_TRANSFER_CH, SMPTE_ST2084_TRANSFER_CH, HLG_OETF_TRANSFER_CH},
{ITUR_BT709_CODING_EQ, ITU2020_NCL_CODING_EQ},
MXF_SIGNAL_STANDARD_SMPTE274M /* or None */, {16, 9}, {42, 0}, MXF_COLOR_SITING_COSITING},
{3840, 2160, false,
{ITU2020_COLOR_PRIM, g_Null_UL},
{ITU2020_TRANSFER_CH, SMPTE_ST2084_TRANSFER_CH, HLG_OETF_TRANSFER_CH, g_Null_UL},
{ITU2020_NCL_CODING_EQ, g_Null_UL},
MXF_SIGNAL_STANDARD_NONE, {16, 9}, {1, 0}, MXF_COLOR_SITING_COSITING}
};

Expand Down Expand Up @@ -377,18 +367,71 @@ void RDD36MXFDescriptorHelper::UpdateFileDescriptor(RDD36EssenceParser *essence_

size_t i;
for (i = 0; i < BMX_ARRAY_SIZE(DEFAULT_PARAM_MATCHES); i++) {
bool match = false;
if (DEFAULT_PARAM_MATCHES[i].width == width &&
DEFAULT_PARAM_MATCHES[i].height == height &&
DEFAULT_PARAM_MATCHES[i].is_full_frame == is_full_frame &&
(DEFAULT_PARAM_MATCHES[i].color_primaries == color_primaries ||
color_primaries == g_Null_UL) &&
(DEFAULT_PARAM_MATCHES[i].transfer_characteristic == transfer_characteristic ||
transfer_characteristic == g_Null_UL) &&
(DEFAULT_PARAM_MATCHES[i].matrix_coefficients == matrix_coefficients ||
matrix_coefficients == g_Null_UL))
DEFAULT_PARAM_MATCHES[i].is_full_frame == is_full_frame)
{
if (!cdci_descriptor->haveSignalStandard())
cdci_descriptor->setSignalStandard(DEFAULT_PARAM_MATCHES[i].signal_standard);
match = true;
}
if (match && color_primaries != g_Null_UL) {
// Check at least one color primary matches
match = false;
for (size_t k = 0; k < BMX_ARRAY_SIZE(DEFAULT_PARAM_MATCHES[i].color_primaries); k++) {
if (DEFAULT_PARAM_MATCHES[i].color_primaries[k] == color_primaries) {
match = true;
break;
} else if (DEFAULT_PARAM_MATCHES[i].color_primaries[k] == g_Null_UL) {
break;
}
}
}
if (match && transfer_characteristic != g_Null_UL) {
// Check at least one transfer characteristic matches
match = false;
for (size_t k = 0; k < BMX_ARRAY_SIZE(DEFAULT_PARAM_MATCHES[i].transfer_characteristic); k++) {
if (DEFAULT_PARAM_MATCHES[i].transfer_characteristic[k] == transfer_characteristic) {
match = true;
break;
} else if (DEFAULT_PARAM_MATCHES[i].transfer_characteristic[k] == g_Null_UL) {
break;
}
}
}
if (match && matrix_coefficients != g_Null_UL) {
// Check at least one matrix coefficients matches
match = false;
for (size_t k = 0; k < BMX_ARRAY_SIZE(DEFAULT_PARAM_MATCHES[i].matrix_coefficients); k++) {
if (DEFAULT_PARAM_MATCHES[i].matrix_coefficients[k] == matrix_coefficients) {
match = true;
break;
} else if (DEFAULT_PARAM_MATCHES[i].matrix_coefficients[k] == g_Null_UL) {
break;
}
}
}
if (match) {
if (!cdci_descriptor->haveSignalStandard()) {
// Only set a 296M or 274M signal standard if the colorimetry matches BT709
if (DEFAULT_PARAM_MATCHES[i].signal_standard == MXF_SIGNAL_STANDARD_SMPTE296M ||
DEFAULT_PARAM_MATCHES[i].signal_standard == MXF_SIGNAL_STANDARD_SMPTE274M)
{
if ((color_primaries == ITU709_COLOR_PRIM || color_primaries == g_Null_UL) &&
(transfer_characteristic == ITUR_BT709_TRANSFER_CH || transfer_characteristic == g_Null_UL) &&
(matrix_coefficients == ITUR_BT709_CODING_EQ || matrix_coefficients == g_Null_UL))
{
cdci_descriptor->setSignalStandard(DEFAULT_PARAM_MATCHES[i].signal_standard);
}
else
{
cdci_descriptor->setSignalStandard(MXF_SIGNAL_STANDARD_NONE);
}
}
else
{
cdci_descriptor->setSignalStandard(DEFAULT_PARAM_MATCHES[i].signal_standard);
}
}
if (!cdci_descriptor->haveAspectRatio())
cdci_descriptor->setAspectRatio(DEFAULT_PARAM_MATCHES[i].aspect_ratio);
if (!cdci_descriptor->haveVideoLineMap()) {
Expand Down
22 changes: 15 additions & 7 deletions test/create_test_essence.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,8 @@ typedef enum
TYPE_RDD36_422 = 55,
TYPE_RDD36_4444 = 56,
TYPE_16BIT_PCM_SAMPLES = 57,
TYPE_END = 58,
TYPE_RDD36_422_ITU2020 = 58,
TYPE_END = 59,
} EssenceType;

typedef struct
Expand Down Expand Up @@ -719,7 +720,7 @@ static void write_rdd36(FILE *file, int type, unsigned int duration)
set_rdd36_bits(data, &bit_offset, 32, 0x20626d78); // encoder identifier
set_rdd36_bits(data, &bit_offset, 16, 1920); // width
set_rdd36_bits(data, &bit_offset, 16, 1080); // height
if (type == TYPE_RDD36_422)
if (type == TYPE_RDD36_422 || type == TYPE_RDD36_422_ITU2020)
set_rdd36_bits(data, &bit_offset, 2, 2); // chroma_format
else
set_rdd36_bits(data, &bit_offset, 2, 3); // chroma_format
Expand All @@ -730,15 +731,21 @@ static void write_rdd36(FILE *file, int type, unsigned int duration)
set_rdd36_bits(data, &bit_offset, 2, 0); // interlace mode
set_rdd36_bits(data, &bit_offset, 2, 0); // reserved
set_rdd36_bits(data, &bit_offset, 4, 3); // aspect ratio
if (type == TYPE_RDD36_422)
if (type == TYPE_RDD36_422 || type == TYPE_RDD36_422_ITU2020)
set_rdd36_bits(data, &bit_offset, 4, 3); // frame rate
else
set_rdd36_bits(data, &bit_offset, 4, 6); // frame rate
set_rdd36_bits(data, &bit_offset, 8, 1); // color primaries
set_rdd36_bits(data, &bit_offset, 8, 1); // transfer characteristic
set_rdd36_bits(data, &bit_offset, 8, 1); // matrix coefficients
if (type == TYPE_RDD36_422_ITU2020) {
set_rdd36_bits(data, &bit_offset, 8, 9); // color primaries
set_rdd36_bits(data, &bit_offset, 8, 15); // transfer characteristic
set_rdd36_bits(data, &bit_offset, 8, 9); // matrix coefficients
} else {
set_rdd36_bits(data, &bit_offset, 8, 1); // color primaries
set_rdd36_bits(data, &bit_offset, 8, 1); // transfer characteristic
set_rdd36_bits(data, &bit_offset, 8, 1); // matrix coefficients
}
set_rdd36_bits(data, &bit_offset, 4, 0); // reserved
if (type == TYPE_RDD36_422)
if (type == TYPE_RDD36_422 || type == TYPE_RDD36_422_ITU2020)
set_rdd36_bits(data, &bit_offset, 4, 0); // alpha channel type
else
set_rdd36_bits(data, &bit_offset, 4, 1); // alpha channel type
Expand Down Expand Up @@ -1129,6 +1136,7 @@ int main(int argc, const char **argv)
break;
case TYPE_RDD36_422:
case TYPE_RDD36_4444:
case TYPE_RDD36_422_ITU2020:
write_rdd36(file, type, duration);
break;
case TYPE_VC2:
Expand Down
1 change: 1 addition & 0 deletions test/mxf_op1a/rdd36_422_itu2020.md5
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
778c7df7be0672a91a369da64c6e7dbd
56 changes: 56 additions & 0 deletions test/mxf_op1a/test_rdd36.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,59 @@ set(tests
)

run_tests("${tests}" 3)


# Test with ITU 2020 colorimetry

include("${TEST_SOURCE_DIR}/../testing.cmake")

set(create_test_video ${CREATE_TEST_ESSENCE}
-t 58
-d 3
video_rdd36_422_itu2020
)

if(TEST_MODE STREQUAL "check")
set(output_file test_rdd36_422_itu2020.mxf)
elseif(TEST_MODE STREQUAL "samples")
file(MAKE_DIRECTORY ${BMX_TEST_SAMPLES_DIR})

set(output_file ${BMX_TEST_SAMPLES_DIR}/test_rdd36_422_itu2020.mxf)
else()
set(output_file test_rdd36_422_itu2020.mxf)
endif()

set(checksum_file rdd36_422_itu2020.md5)

set(create_test_audio ${CREATE_TEST_ESSENCE}
-t 1
-d 3
audio_rdd36_422_itu2020
)

set(create_command ${RAW2BMX}
--regtest
-t op1a
-y 10:11:12:13
--clip test
-o ${output_file}
-a 16:9 --rdd36_422 video_rdd36_422_itu2020
-q 16 --locked true --pcm audio_rdd36_422_itu2020
-q 16 --locked true --pcm audio_rdd36_422_itu2020
)

run_test_a(
"${TEST_MODE}"
"${BMX_TEST_WITH_VALGRIND}"
"${create_test_video}"
"${create_test_audio}"
""
"${create_command}"
""
""
""
"${output_file}"
"${checksum_file}"
""
""
)

0 comments on commit eb4df19

Please sign in to comment.