Extract frame info read/write to new class.
authorCarl Hetherington <cth@carlh.net>
Tue, 26 Mar 2024 21:43:10 +0000 (22:43 +0100)
committerCarl Hetherington <cth@carlh.net>
Sun, 21 Apr 2024 21:18:23 +0000 (23:18 +0200)
src/lib/frame_info.cc [new file with mode: 0644]
src/lib/frame_info.h [new file with mode: 0644]
src/lib/reel_writer.cc
src/lib/reel_writer.h
src/lib/writer.cc
src/lib/wscript
test/reel_writer_test.cc

diff --git a/src/lib/frame_info.cc b/src/lib/frame_info.cc
new file mode 100644 (file)
index 0000000..f348bca
--- /dev/null
@@ -0,0 +1,84 @@
+/*
+    Copyright (C) 2024 Carl Hetherington <cth@carlh.net>
+
+    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 <http://www.gnu.org/licenses/>.
+
+*/
+
+
+#include "frame_info.h"
+#include <string>
+
+
+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<InfoFileHandle> 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<InfoFileHandle> 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 (file)
index 0000000..a5a22bd
--- /dev/null
@@ -0,0 +1,45 @@
+/*
+    Copyright (C) 2024 Carl Hetherington <cth@carlh.net>
+
+    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 <http://www.gnu.org/licenses/>.
+
+*/
+
+
+#include "film.h"
+#include <dcp/frame_info.h>
+#include <memory>
+
+
+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<InfoFileHandle> info_file, Frame frame, Eyes eyes);
+
+       void write(std::shared_ptr<InfoFileHandle> 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);
+};
+
index 1cca3fd17e3355dba20b8425c8c47a51dc8d5375..201c23e71763d40fe9e70992b6b7a6984450a436 100644 (file)
@@ -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<InfoFileHandle> 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<const Data> 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_ptr<InfoFil
        /* Read the data from the info file; for 3D we just check the left
           frames until we find a good one.
        */
-       auto const info = read_frame_info (info_file, frame, film()->three_d() ? Eyes::LEFT : Eyes::BOTH);
+       auto const info = J2KFrameInfo(info_file, frame, film()->three_d() ? Eyes::LEFT : Eyes::BOTH);
 
        bool ok = true;
 
index 6f47c6740cc442a32e3cab4bcce6987a92139e0c..30abdd5635dea0eeee65ab91a711d4af88d7998f 100644 (file)
@@ -95,14 +95,10 @@ public:
                return _first_nonexistent_frame;
        }
 
-       dcp::FrameInfo read_frame_info (std::shared_ptr<InfoFileHandle> 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<InfoFileHandle> info_file, Frame frame) const;
        std::shared_ptr<dcp::SubtitleAsset> empty_text_asset (TextType type, boost::optional<DCPTextTrack> track, bool with_dummy) const;
@@ -146,6 +142,4 @@ private:
        std::shared_ptr<dcp::AtmosAssetWriter> _atmos_asset_writer;
 
        mutable FontMetrics _font_metrics;
-
-       static int const _info_size;
 };
index fbe2d248d5c952c3112f1e5f9f7184ae3b4073c3..1c04f40657f7bcdc25fdcacb6db9d8ce71690678 100644 (file)
@@ -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<InfoFileHandle> 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));
 
index 152d3abafb89e716a48ad743740134b21c10a701..8e839cb49e66f1e074044e89b8ff5d08d0305ae9 100644 (file)
@@ -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
index ec246989804a4fa08901c7738cbaa98669d5829a..f81e8e333af111bd60aab5cb162d21031d8ae36b 100644 (file)
@@ -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<InfoFileHandle> file, Frame frame, Eyes eyes)
+static bool equal(J2KFrameInfo a, shared_ptr<InfoFileHandle> 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));
        }
 }