return i->second;
}
-shared_ptr<InfoFileHandle>
-Film::info_file_handle (DCPTimePeriod period, bool read) const
-{
- return std::make_shared<InfoFileHandle>(_info_file_mutex, info_file(period), read);
-}
-
-InfoFileHandle::InfoFileHandle (boost::mutex& mutex, boost::filesystem::path path, bool read)
- : _lock (mutex)
- , _file(path, read ? "rb" : (dcp::filesystem::exists(path) ? "r+b" : "wb"))
-{
- if (!_file) {
- throw OpenFileError(path, _file.open_error(), read ? OpenFileError::READ : (dcp::filesystem::exists(path) ? OpenFileError::READ_WRITE : OpenFileError::WRITE));
- }
-}
-
/** Add FFOC and LFOC markers to a list if they are not already there */
void
struct recover_test_2d_encrypted;
-class InfoFileHandle
-{
-public:
- InfoFileHandle (boost::mutex& mutex, boost::filesystem::path file, bool read);
-
- InfoFileHandle(InfoFileHandle const&) = delete;
- InfoFileHandle& operator=(InfoFileHandle const&) = delete;
- InfoFileHandle(InfoFileHandle&&) = delete;
- InfoFileHandle& operator=(InfoFileHandle&&) = delete;
-
- dcp::File& get () {
- return _file;
- }
-
-private:
- friend class Film;
-
- boost::mutex::scoped_lock _lock;
- dcp::File _file;
-};
-
-
/** @class Film
*
* @brief A representation of some audio, video, subtitle and closed-caption content,
Film (Film const&) = delete;
Film& operator= (Film const&) = delete;
- std::shared_ptr<InfoFileHandle> info_file_handle (dcpomatic::DCPTimePeriod period, bool read) const;
boost::filesystem::path j2c_path (int, Frame, Eyes, bool) const;
boost::filesystem::path audio_analysis_path (std::shared_ptr<const Playlist>) const;
std::map<std::string, std::string> _ui_state;
- mutable boost::mutex _info_file_mutex;
-
boost::signals2::scoped_connection _playlist_change_connection;
boost::signals2::scoped_connection _playlist_order_changed_connection;
boost::signals2::scoped_connection _playlist_content_change_connection;
}
-J2KFrameInfo::J2KFrameInfo(shared_ptr<InfoFileHandle> info_file, Frame frame, Eyes eyes)
+J2KFrameInfo::J2KFrameInfo(dcp::File& 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));
+ info_file.seek(position(frame, eyes), SEEK_SET);
+ info_file.checked_read(&offset, sizeof(offset));
+ info_file.checked_read(&size, sizeof(size));
char hash_buffer[33];
- info_file->get().checked_read(hash_buffer, 32);
+ info_file.checked_read(hash_buffer, 32);
hash_buffer[32] = '\0';
hash = hash_buffer;
}
/** @param frame reel-relative frame */
void
-J2KFrameInfo::write(shared_ptr<InfoFileHandle> info_file, Frame frame, Eyes eyes) const
+J2KFrameInfo::write(dcp::File& 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());
+ info_file.seek(position(frame, eyes), SEEK_SET);
+ info_file.checked_write(&offset, sizeof(offset));
+ info_file.checked_write(&size, sizeof(size));
+ info_file.checked_write(hash.c_str(), hash.size());
}
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;
+ /** Seek to the required position in info_file and read the info for
+ * the given frame and eyes.
+ */
+ J2KFrameInfo(dcp::File& info_file, Frame frame, Eyes eyes);
+
+ /** Seek to the required position in info_file and write the info for
+ * the given frame and eyes.
+ */
+ void write(dcp::File& info_file, Frame frame, Eyes eyes) const;
static int size_on_disk() {
return _size_on_disk;
, _content_summary (film()->content_summary(period))
, _job (job)
, _text_only (text_only)
+ , _info_file(film()->info_file(period), dcp::filesystem::exists(film()->info_file(period)) ? "r+b" : "wb")
, _font_metrics(film()->frame_size().height)
{
+ if (!_info_file) {
+ auto const info_file_path = film()->info_file(period);
+ throw OpenFileError(info_file_path, _info_file.open_error(), dcp::filesystem::exists(info_file_path) ? OpenFileError::READ_WRITE : OpenFileError::WRITE);
+ }
+
_default_font = dcp::ArrayData(default_font_file());
if (text_only) {
LOG_GENERAL ("Opened existing asset at %1", asset.string());
}
- shared_ptr<InfoFileHandle> info_file;
-
- try {
- info_file = film()->info_file_handle (_period, true);
- } catch (OpenFileError &) {
- LOG_GENERAL_NC ("Could not open film info file");
- return 0;
- }
-
/* Offset of the last dcp::FrameInfo in the info file */
- 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())
+ int const n = (dcp::filesystem::file_size(_info_file.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.path()), J2KFrameInfo::size_on_disk())
Frame first_nonexistent_frame;
if (film()->three_d()) {
first_nonexistent_frame = n;
}
- while (!existing_picture_frame_ok(asset_file, info_file, first_nonexistent_frame) && first_nonexistent_frame > 0) {
+ while (!existing_picture_frame_ok(asset_file, first_nonexistent_frame) && first_nonexistent_frame > 0) {
--first_nonexistent_frame;
}
}
auto fin = J2KFrameInfo(_j2k_picture_asset_writer->write(encoded->data(), encoded->size()));
- fin.write(film()->info_file_handle(_period, false), frame, eyes);
+ fin.write(_info_file, frame, eyes);
_last_written[eyes] = encoded;
}
void
-ReelWriter::fake_write(dcp::J2KFrameInfo const& info)
+ReelWriter::fake_write(Frame frame, Eyes eyes)
{
if (!_j2k_picture_asset_writer) {
/* We're not writing any data */
return;
}
- _j2k_picture_asset_writer->fake_write(info);
+ _j2k_picture_asset_writer->fake_write(J2KFrameInfo(_info_file, frame, eyes));
}
}
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);
+ fin.write(_info_file, frame, eyes);
}
bool
-ReelWriter::existing_picture_frame_ok (dcp::File& asset_file, shared_ptr<InfoFileHandle> info_file, Frame frame) const
+ReelWriter::existing_picture_frame_ok(dcp::File& asset_file, Frame frame)
{
LOG_GENERAL ("Checking existing picture frame %1", frame);
/* Read the data from the info file; for 3D we just check the left
frames until we find a good one.
*/
- auto const info = J2KFrameInfo(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;
);
void write (std::shared_ptr<const dcp::Data> encoded, Frame frame, Eyes eyes);
- void fake_write(dcp::J2KFrameInfo const& info);
+ void fake_write(Frame frame, Eyes eyes);
void repeat_write (Frame frame, Eyes eyes);
void write (std::shared_ptr<const AudioBuffers> audio);
void write(PlayerText text, TextType type, boost::optional<DCPTextTrack> track, dcpomatic::DCPTimePeriod period, FontIdMap const& fonts, std::shared_ptr<dcpomatic::Font> chosen_interop_font);
friend struct ::write_frame_info_test;
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;
+ bool existing_picture_frame_ok(dcp::File& asset_file, Frame frame);
std::shared_ptr<dcp::TextAsset> empty_text_asset (TextType type, boost::optional<DCPTextTrack> track, bool with_dummy) const;
std::shared_ptr<dcp::ReelPictureAsset> create_reel_picture (std::shared_ptr<dcp::Reel> reel, std::list<ReferencedReelAsset> const & refs) const;
dcp::ArrayData _default_font;
+ dcp::File _info_file;
+
std::shared_ptr<dcp::J2KPictureAsset> _j2k_picture_asset;
std::shared_ptr<dcp::MPEG2PictureAsset> _mpeg2_picture_asset;
/** picture asset writer, or 0 if we are not writing any picture because we already have one */
int reel_index = 0;
auto const reels = film()->reels();
for (auto p: reels) {
- _reels.push_back(ReelWriter(weak_film, p, job, reel_index++, reels.size(), text_only, _output_dir));
+ _reels.emplace_back(weak_film, p, job, reel_index++, reels.size(), text_only, _output_dir);
}
_last_written.resize (reels.size());
_full_condition.wait (lock);
}
- size_t const reel = video_reel (frame);
- Frame const frame_in_reel = frame - _reels[reel].start ();
+ DCPOMATIC_ASSERT((film()->three_d() && eyes != Eyes::BOTH) || (!film()->three_d() && eyes == Eyes::BOTH));
QueueItem qi;
qi.type = QueueItem::Type::FAKE;
- qi.info = J2KFrameInfo(film()->info_file_handle(_reels[reel].period(), true), frame_in_reel, eyes);
-
- DCPOMATIC_ASSERT((film()->three_d() && eyes != Eyes::BOTH) || (!film()->three_d() && eyes == Eyes::BOTH));
-
+ auto const reel = video_reel(frame);
qi.reel = reel;
- qi.frame = frame_in_reel;
+ qi.frame = frame - _reels[reel].start();
qi.eyes = eyes;
_queue.push_back(qi);
if (i.type == QueueItem::Type::FULL) {
LOG_WARNING (N_("- type FULL, frame %1, eyes %2"), i.frame, (int) i.eyes);
} else {
- LOG_WARNING (N_("- type FAKE, size %1, frame %2, eyes %3"), i.info.size, i.frame, (int) i.eyes);
+ LOG_WARNING(N_("- type FAKE, frame %1, eyes %2"), i.frame, static_cast<int>(i.eyes));
}
}
}
break;
case QueueItem::Type::FAKE:
LOG_DEBUG_ENCODE (N_("Writer FAKE-writes %1"), qi.frame);
- reel.fake_write(qi.info);
+ reel.fake_write(qi.frame, qi.eyes);
++_fake_written;
break;
case QueueItem::Type::REPEAT:
/** encoded data for FULL */
std::shared_ptr<const dcp::Data> encoded;
- /** info for FAKE */
- dcp::J2KFrameInfo info;
/** reel index */
size_t reel = 0;
/** frame index within the reel */
using boost::optional;
-static bool equal(J2KFrameInfo a, shared_ptr<InfoFileHandle> file, Frame frame, Eyes eyes)
+static bool equal(J2KFrameInfo a, dcp::File& file, Frame frame, Eyes eyes)
{
auto b = J2KFrameInfo(file, frame, eyes);
return a.offset == b.offset && a.size == b.size && a.hash == b.hash;
{
auto film = new_test_film("write_frame_info_test");
dcpomatic::DCPTimePeriod const period (dcpomatic::DCPTime(0), dcpomatic::DCPTime(96000));
- ReelWriter writer(film, period, shared_ptr<Job>(), 0, 1, false, "foo");
-
- /* Write the first one */
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, file, 0, Eyes::LEFT));
- }
-
- /* Write some more */
-
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, file, 0, Eyes::LEFT));
- BOOST_CHECK(equal(info2, file, 5, Eyes::RIGHT));
- }
-
J2KFrameInfo info3(12494, 99157123, "xxxxyyyyabc12356ffsfdsf456339522");
- info3.write(film->info_file_handle(period, false), 10, Eyes::LEFT);
+ J2KFrameInfo info4(55512494, 123599157123, "ABCDEFGyabc12356ffsfdsf4563395ZZ");
{
- auto file = film->info_file_handle(period, true);
- BOOST_CHECK(equal(info1, file, 0, Eyes::LEFT));
- BOOST_CHECK(equal(info2, file, 5, Eyes::RIGHT));
- BOOST_CHECK(equal(info3, file, 10, Eyes::LEFT));
+ ReelWriter writer(film, period, shared_ptr<Job>(), 0, 1, false, "foo");
+ info1.write(writer._info_file, 0, Eyes::LEFT);
+ info2.write(writer._info_file, 5, Eyes::RIGHT);
+ info3.write(writer._info_file, 10, Eyes::LEFT);
}
- /* Overwrite one */
-
- J2KFrameInfo info4(55512494, 123599157123, "ABCDEFGyabc12356ffsfdsf4563395ZZ");
- info4.write(film->info_file_handle(period, false), 5, Eyes::RIGHT);
+ auto file1 = dcp::File(film->info_file(period), "rb");
+ BOOST_CHECK(equal(info1, file1, 0, Eyes::LEFT));
+ BOOST_CHECK(equal(info1, file1, 0, Eyes::LEFT));
+ BOOST_CHECK(equal(info2, file1, 5, Eyes::RIGHT));
+ BOOST_CHECK(equal(info1, file1, 0, Eyes::LEFT));
+ BOOST_CHECK(equal(info2, file1, 5, Eyes::RIGHT));
+ BOOST_CHECK(equal(info3, file1, 10, Eyes::LEFT));
{
- auto file = film->info_file_handle(period, true);
- BOOST_CHECK(equal(info1, file, 0, Eyes::LEFT));
- BOOST_CHECK(equal(info4, file, 5, Eyes::RIGHT));
- BOOST_CHECK(equal(info3, file, 10, Eyes::LEFT));
+ ReelWriter writer(film, period, shared_ptr<Job>(), 0, 1, false, "foo");
+
+ /* Overwrite one */
+ info4.write(writer._info_file, 5, Eyes::RIGHT);
}
+
+ auto file2 = dcp::File(film->info_file(period), "rb");
+ BOOST_CHECK(equal(info1, file2, 0, Eyes::LEFT));
+ BOOST_CHECK(equal(info4, file2, 5, Eyes::RIGHT));
+ BOOST_CHECK(equal(info3, file2, 10, Eyes::LEFT));
}