+ ASDCP::ATMOS::MXFReader ref_reader;
+ BOOST_REQUIRE (!ASDCP_FAILURE(ref_reader.OpenRead(ref.string().c_str())));
+
+ ASDCP::ATMOS::AtmosDescriptor ref_desc;
+ BOOST_REQUIRE (!ASDCP_FAILURE(ref_reader.FillAtmosDescriptor(ref_desc)));
+
+ ASDCP::ATMOS::MXFReader check_reader;
+ BOOST_REQUIRE (!ASDCP_FAILURE(check_reader.OpenRead(check.string().c_str())));
+
+ ASDCP::ATMOS::AtmosDescriptor check_desc;
+ BOOST_REQUIRE (!ASDCP_FAILURE(check_reader.FillAtmosDescriptor(check_desc)));
+
+ if (ref_desc.EditRate.Numerator != check_desc.EditRate.Numerator) {
+ if (verbose) {
+ std::cout << "EditRate.Numerator differs.\n";
+ }
+ return false;
+ }
+ if (ref_desc.EditRate.Denominator != check_desc.EditRate.Denominator) {
+ if (verbose) {
+ std::cout << "EditRate.Denominator differs.\n";
+ }
+ return false;
+ }
+ if (ref_desc.ContainerDuration != check_desc.ContainerDuration) {
+ if (verbose) {
+ std::cout << "EditRate.ContainerDuration differs.\n";
+ }
+ return false;
+ }
+ if (ref_desc.FirstFrame != check_desc.FirstFrame) {
+ if (verbose) {
+ std::cout << "EditRate.FirstFrame differs.\n";
+ }
+ return false;
+ }
+ if (ref_desc.MaxChannelCount != check_desc.MaxChannelCount) {
+ if (verbose) {
+ std::cout << "EditRate.MaxChannelCount differs.\n";
+ }
+ return false;
+ }
+ if (ref_desc.MaxObjectCount != check_desc.MaxObjectCount) {
+ if (verbose) {
+ std::cout << "EditRate.MaxObjectCount differs.\n";
+ }
+ return false;
+ }
+ if (ref_desc.AtmosVersion != check_desc.AtmosVersion) {
+ if (verbose) {
+ std::cout << "EditRate.AtmosVersion differs.\n";
+ }
+ return false;
+ }
+
+ ASDCP::DCData::FrameBuffer ref_buffer (Kumu::Megabyte);
+ ASDCP::DCData::FrameBuffer check_buffer (Kumu::Megabyte);
+ for (size_t i = 0; i < ref_desc.ContainerDuration; ++i) {
+ ref_reader.ReadFrame (i, ref_buffer, 0);
+ check_reader.ReadFrame (i, check_buffer, 0);
+ if (memcmp(ref_buffer.RoData(), check_buffer.RoData(), ref_buffer.Size())) {
+ if (verbose) {
+ std::cout << "data differs.\n";
+ }
+ return false;
+ }
+ }
+
+ return true;
+}
+
+
+static
+double
+rms_error (boost::filesystem::path ref, boost::filesystem::path check)
+{
+ FFmpegImageProxy ref_proxy (ref);
+ auto ref_image = ref_proxy.image(false).image;
+ FFmpegImageProxy check_proxy (check);
+ auto check_image = check_proxy.image(false).image;
+
+ BOOST_REQUIRE_EQUAL (ref_image->pixel_format(), check_image->pixel_format());
+ AVPixelFormat const format = ref_image->pixel_format();
+
+ BOOST_REQUIRE (ref_image->size() == check_image->size());
+ int const width = ref_image->size().width;
+ int const height = ref_image->size().height;
+
+ double sum_square = 0;
+ switch (format) {
+ case AV_PIX_FMT_RGBA:
+ {
+ for (int y = 0; y < height; ++y) {
+ uint8_t* p = ref_image->data()[0] + y * ref_image->stride()[0];
+ uint8_t* q = check_image->data()[0] + y * check_image->stride()[0];
+ for (int x = 0; x < width; ++x) {
+ for (int c = 0; c < 4; ++c) {
+ sum_square += pow((*p++ - *q++), 2);
+ }
+ }
+ }
+ break;
+ }
+ case AV_PIX_FMT_RGB24:
+ {
+ for (int y = 0; y < height; ++y) {
+ uint8_t* p = ref_image->data()[0] + y * ref_image->stride()[0];
+ uint8_t* q = check_image->data()[0] + y * check_image->stride()[0];
+ for (int x = 0; x < width; ++x) {
+ for (int c = 0; c < 3; ++c) {
+ sum_square += pow((*p++ - *q++), 2);
+ }
+ }
+ }
+ break;
+ }
+ case AV_PIX_FMT_RGB48BE:
+ {
+ for (int y = 0; y < height; ++y) {
+ uint16_t* p = reinterpret_cast<uint16_t*>(ref_image->data()[0] + y * ref_image->stride()[0]);
+ uint16_t* q = reinterpret_cast<uint16_t*>(check_image->data()[0] + y * check_image->stride()[0]);
+ for (int x = 0; x < width; ++x) {
+ for (int c = 0; c < 3; ++c) {
+ sum_square += pow((*p++ - *q++), 2);
+ }
+ }
+ }
+ break;
+ }
+ default:
+ BOOST_REQUIRE_MESSAGE (false, "unrecognised pixel format " << format);
+ }