From f7518583f90a866a07d8069a78bebcea82b2b248 Mon Sep 17 00:00:00 2001 From: Carl Hetherington Date: Tue, 26 Mar 2024 22:43:10 +0100 Subject: [PATCH] Extract frame info read/write to new class. --- src/lib/frame_info.cc | 84 ++++++++++++++++++++++++++++++++++++++++ src/lib/frame_info.h | 45 +++++++++++++++++++++ src/lib/reel_writer.cc | 65 ++++--------------------------- src/lib/reel_writer.h | 6 --- src/lib/writer.cc | 7 +--- src/lib/wscript | 1 + test/reel_writer_test.cc | 39 ++++++++++--------- 7 files changed, 160 insertions(+), 87 deletions(-) create mode 100644 src/lib/frame_info.cc create mode 100644 src/lib/frame_info.h diff --git a/src/lib/frame_info.cc b/src/lib/frame_info.cc new file mode 100644 index 000000000..f348bca6a --- /dev/null +++ b/src/lib/frame_info.cc @@ -0,0 +1,84 @@ +/* + Copyright (C) 2024 Carl Hetherington + + This file is part of DCP-o-matic. + + DCP-o-matic is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + DCP-o-matic is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with DCP-o-matic. If not, see . + +*/ + + +#include "frame_info.h" +#include + + +using std::shared_ptr; +using std::string; + + +J2KFrameInfo::J2KFrameInfo(uint64_t offset_, uint64_t size_, string hash_) + : dcp::J2KFrameInfo(offset_, size_, hash_) +{ + +} + + +J2KFrameInfo::J2KFrameInfo(dcp::J2KFrameInfo const& info) + : dcp::J2KFrameInfo(info) +{ + +} + + +J2KFrameInfo::J2KFrameInfo(shared_ptr info_file, Frame frame, Eyes eyes) +{ + info_file->get().seek(position(frame, eyes), SEEK_SET); + info_file->get().checked_read(&offset, sizeof(offset)); + info_file->get().checked_read(&size, sizeof(size)); + + char hash_buffer[33]; + info_file->get().checked_read(hash_buffer, 32); + hash_buffer[32] = '\0'; + hash = hash_buffer; +} + + +long +J2KFrameInfo::position(Frame frame, Eyes eyes) const +{ + switch (eyes) { + case Eyes::BOTH: + return frame * _size_on_disk; + case Eyes::LEFT: + return frame * _size_on_disk * 2; + case Eyes::RIGHT: + return frame * _size_on_disk * 2 + _size_on_disk; + default: + DCPOMATIC_ASSERT(false); + } + + DCPOMATIC_ASSERT(false); +} + + +/** @param frame reel-relative frame */ +void +J2KFrameInfo::write(shared_ptr info_file, Frame frame, Eyes eyes) const +{ + info_file->get().seek(position(frame, eyes), SEEK_SET); + info_file->get().checked_write(&offset, sizeof(offset)); + info_file->get().checked_write(&size, sizeof(size)); + info_file->get().checked_write(hash.c_str(), hash.size()); +} + diff --git a/src/lib/frame_info.h b/src/lib/frame_info.h new file mode 100644 index 000000000..a5a22bd9e --- /dev/null +++ b/src/lib/frame_info.h @@ -0,0 +1,45 @@ +/* + Copyright (C) 2024 Carl Hetherington + + This file is part of DCP-o-matic. + + DCP-o-matic is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + DCP-o-matic is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with DCP-o-matic. If not, see . + +*/ + + +#include "film.h" +#include +#include + + +class J2KFrameInfo : public dcp::J2KFrameInfo +{ +public: + J2KFrameInfo(dcp::J2KFrameInfo const& info); + J2KFrameInfo(uint64_t offset_, uint64_t size_, std::string hash_); + J2KFrameInfo(std::shared_ptr info_file, Frame frame, Eyes eyes); + + void write(std::shared_ptr info_file, Frame frame, Eyes eyes) const; + + static int size_on_disk() { + return _size_on_disk; + } + +private: + long position(Frame frame, Eyes eyes) const; + + static constexpr auto _size_on_disk = 32 + sizeof(dcp::J2KFrameInfo::offset) + sizeof(dcp::J2KFrameInfo::size); +}; + diff --git a/src/lib/reel_writer.cc b/src/lib/reel_writer.cc index 1cca3fd17..201c23e71 100644 --- a/src/lib/reel_writer.cc +++ b/src/lib/reel_writer.cc @@ -28,6 +28,7 @@ #include "digester.h" #include "film.h" #include "film_util.h" +#include "frame_info.h" #include "image.h" #include "image_png.h" #include "job.h" @@ -81,9 +82,6 @@ using dcp::raw_convert; using namespace dcpomatic; -int const ReelWriter::_info_size = 48; - - static dcp::MXFMetadata mxf_metadata () { @@ -215,53 +213,6 @@ ReelWriter::ReelWriter ( } -/** @param frame reel-relative frame */ -void -ReelWriter::write_frame_info (Frame frame, Eyes eyes, dcp::FrameInfo info) const -{ - auto handle = film()->info_file_handle(_period, false); - handle->get().seek(frame_info_position(frame, eyes), SEEK_SET); - handle->get().checked_write(&info.offset, sizeof(info.offset)); - handle->get().checked_write(&info.size, sizeof(info.size)); - handle->get().checked_write(info.hash.c_str(), info.hash.size()); -} - - -dcp::FrameInfo -ReelWriter::read_frame_info (shared_ptr info, Frame frame, Eyes eyes) const -{ - dcp::FrameInfo frame_info; - info->get().seek(frame_info_position(frame, eyes), SEEK_SET); - info->get().checked_read(&frame_info.offset, sizeof(frame_info.offset)); - info->get().checked_read(&frame_info.size, sizeof(frame_info.size)); - - char hash_buffer[33]; - info->get().checked_read(hash_buffer, 32); - hash_buffer[32] = '\0'; - frame_info.hash = hash_buffer; - - return frame_info; -} - - -long -ReelWriter::frame_info_position (Frame frame, Eyes eyes) const -{ - switch (eyes) { - case Eyes::BOTH: - return frame * _info_size; - case Eyes::LEFT: - return frame * _info_size * 2; - case Eyes::RIGHT: - return frame * _info_size * 2 + _info_size; - default: - DCPOMATIC_ASSERT (false); - } - - DCPOMATIC_ASSERT (false); -} - - Frame ReelWriter::check_existing_picture_asset (boost::filesystem::path asset) { @@ -290,8 +241,8 @@ ReelWriter::check_existing_picture_asset (boost::filesystem::path asset) } /* Offset of the last dcp::FrameInfo in the info file */ - int const n = (dcp::filesystem::file_size(info_file->get().path()) / _info_size) - 1; - LOG_GENERAL ("The last FI is %1; info file is %2, info size %3", n, dcp::filesystem::file_size(info_file->get().path()), _info_size); + int const n = (dcp::filesystem::file_size(info_file->get().path()) / J2KFrameInfo::size_on_disk()) - 1; + LOG_GENERAL("The last FI is %1; info file is %2, info size %3", n, dcp::filesystem::file_size(info_file->get().path()), J2KFrameInfo::size_on_disk()) Frame first_nonexistent_frame; if (film()->three_d()) { @@ -326,8 +277,8 @@ ReelWriter::write (shared_ptr encoded, Frame frame, Eyes eyes) return; } - auto fin = _picture_asset_writer->write (encoded->data(), encoded->size()); - write_frame_info (frame, eyes, fin); + auto fin = J2KFrameInfo(_j2k_picture_asset_writer->write(encoded->data(), encoded->size())); + fin.write(film()->info_file_handle(_period, false), frame, eyes); _last_written[eyes] = encoded; } @@ -368,8 +319,8 @@ ReelWriter::repeat_write (Frame frame, Eyes eyes) return; } - auto fin = _picture_asset_writer->write(_last_written[eyes]->data(), _last_written[eyes]->size()); - write_frame_info (frame, eyes, fin); + auto fin = J2KFrameInfo(_j2k_picture_asset_writer->write(_last_written[eyes]->data(), _last_written[eyes]->size())); + fin.write(film()->info_file_handle(_period, false), frame, eyes); } @@ -1012,7 +963,7 @@ ReelWriter::existing_picture_frame_ok (dcp::File& asset_file, shared_ptrthree_d() ? Eyes::LEFT : Eyes::BOTH); + auto const info = J2KFrameInfo(info_file, frame, film()->three_d() ? Eyes::LEFT : Eyes::BOTH); bool ok = true; diff --git a/src/lib/reel_writer.h b/src/lib/reel_writer.h index 6f47c6740..30abdd563 100644 --- a/src/lib/reel_writer.h +++ b/src/lib/reel_writer.h @@ -95,14 +95,10 @@ public: return _first_nonexistent_frame; } - dcp::FrameInfo read_frame_info (std::shared_ptr info, Frame frame, Eyes eyes) const; - private: friend struct ::write_frame_info_test; - void write_frame_info (Frame frame, Eyes eyes, dcp::FrameInfo info) const; - long frame_info_position (Frame frame, Eyes eyes) const; Frame check_existing_picture_asset (boost::filesystem::path asset); bool existing_picture_frame_ok (dcp::File& asset_file, std::shared_ptr info_file, Frame frame) const; std::shared_ptr empty_text_asset (TextType type, boost::optional track, bool with_dummy) const; @@ -146,6 +142,4 @@ private: std::shared_ptr _atmos_asset_writer; mutable FontMetrics _font_metrics; - - static int const _info_size; }; diff --git a/src/lib/writer.cc b/src/lib/writer.cc index fbe2d248d..1c04f4065 100644 --- a/src/lib/writer.cc +++ b/src/lib/writer.cc @@ -30,6 +30,7 @@ #include "dcpomatic_log.h" #include "film.h" #include "film_util.h" +#include "frame_info.h" #include "job.h" #include "log.h" #include "ratio.h" @@ -229,11 +230,7 @@ Writer::fake_write (Frame frame, Eyes eyes) QueueItem qi; qi.type = QueueItem::Type::FAKE; - - { - shared_ptr info_file = film()->info_file_handle(_reels[reel].period(), true); - qi.size = _reels[reel].read_frame_info(info_file, frame_in_reel, eyes).size; - } + qi.size = J2KFrameInfo(film()->info_file_handle(_reels[reel].period(), true), frame_in_reel, eyes).size; DCPOMATIC_ASSERT((film()->three_d() && eyes != Eyes::BOTH) || (!film()->three_d() && eyes == Eyes::BOTH)); diff --git a/src/lib/wscript b/src/lib/wscript index 152d3abaf..8e839cb49 100644 --- a/src/lib/wscript +++ b/src/lib/wscript @@ -98,6 +98,7 @@ sources = """ examine_ffmpeg_subtitles_job.cc exceptions.cc export_config.cc + frame_info.cc file_group.cc file_log.cc filter_graph.cc diff --git a/test/reel_writer_test.cc b/test/reel_writer_test.cc index ec2469898..f81e8e333 100644 --- a/test/reel_writer_test.cc +++ b/test/reel_writer_test.cc @@ -30,6 +30,7 @@ #include "lib/content_factory.h" #include "lib/cross.h" #include "lib/film.h" +#include "lib/frame_info.h" #include "lib/reel_writer.h" #include "lib/video_content.h" #include "test.h" @@ -46,9 +47,9 @@ using std::string; using boost::optional; -static bool equal (dcp::FrameInfo a, ReelWriter const & writer, shared_ptr file, Frame frame, Eyes eyes) +static bool equal(J2KFrameInfo a, shared_ptr file, Frame frame, Eyes eyes) { - auto b = writer.read_frame_info(file, frame, eyes); + auto b = J2KFrameInfo(file, frame, eyes); return a.offset == b.offset && a.size == b.size && a.hash == b.hash; } @@ -61,44 +62,44 @@ BOOST_AUTO_TEST_CASE (write_frame_info_test) /* Write the first one */ - dcp::FrameInfo info1(0, 123, "12345678901234567890123456789012"); - writer.write_frame_info (0, Eyes::LEFT, info1); + J2KFrameInfo info1(0, 123, "12345678901234567890123456789012"); + info1.write(film->info_file_handle(period, false), 0, Eyes::LEFT); { auto file = film->info_file_handle(period, true); - BOOST_CHECK (equal(info1, writer, file, 0, Eyes::LEFT)); + BOOST_CHECK(equal(info1, file, 0, Eyes::LEFT)); } /* Write some more */ - dcp::FrameInfo info2(596, 14921, "123acb789f1234ae782012n456339522"); - writer.write_frame_info (5, Eyes::RIGHT, info2); + J2KFrameInfo info2(596, 14921, "123acb789f1234ae782012n456339522"); + info2.write(film->info_file_handle(period, false), 5, Eyes::RIGHT); { auto file = film->info_file_handle(period, true); - BOOST_CHECK (equal(info1, writer, file, 0, Eyes::LEFT)); - BOOST_CHECK (equal(info2, writer, file, 5, Eyes::RIGHT)); + BOOST_CHECK(equal(info1, file, 0, Eyes::LEFT)); + BOOST_CHECK(equal(info2, file, 5, Eyes::RIGHT)); } - dcp::FrameInfo info3(12494, 99157123, "xxxxyyyyabc12356ffsfdsf456339522"); - writer.write_frame_info (10, Eyes::LEFT, info3); + J2KFrameInfo info3(12494, 99157123, "xxxxyyyyabc12356ffsfdsf456339522"); + info3.write(film->info_file_handle(period, false), 10, Eyes::LEFT); { auto file = film->info_file_handle(period, true); - BOOST_CHECK (equal(info1, writer, file, 0, Eyes::LEFT)); - BOOST_CHECK (equal(info2, writer, file, 5, Eyes::RIGHT)); - BOOST_CHECK (equal(info3, writer, file, 10, Eyes::LEFT)); + BOOST_CHECK(equal(info1, file, 0, Eyes::LEFT)); + BOOST_CHECK(equal(info2, file, 5, Eyes::RIGHT)); + BOOST_CHECK(equal(info3, file, 10, Eyes::LEFT)); } /* Overwrite one */ - dcp::FrameInfo info4(55512494, 123599157123, "ABCDEFGyabc12356ffsfdsf4563395ZZ"); - writer.write_frame_info (5, Eyes::RIGHT, info4); + J2KFrameInfo info4(55512494, 123599157123, "ABCDEFGyabc12356ffsfdsf4563395ZZ"); + info4.write(film->info_file_handle(period, false), 5, Eyes::RIGHT); { auto file = film->info_file_handle(period, true); - BOOST_CHECK (equal(info1, writer, file, 0, Eyes::LEFT)); - BOOST_CHECK (equal(info4, writer, file, 5, Eyes::RIGHT)); - BOOST_CHECK (equal(info3, writer, file, 10, Eyes::LEFT)); + BOOST_CHECK(equal(info1, file, 0, Eyes::LEFT)); + BOOST_CHECK(equal(info4, file, 5, Eyes::RIGHT)); + BOOST_CHECK(equal(info3, file, 10, Eyes::LEFT)); } } -- 2.30.2