diff options
| author | Carl Hetherington <cth@carlh.net> | 2015-10-21 09:23:14 +0100 |
|---|---|---|
| committer | Carl Hetherington <cth@carlh.net> | 2015-10-22 10:30:45 +0100 |
| commit | e25bf0c33f4085f6caa3d0d19a083399a422146a (patch) | |
| tree | b7d1b00e2adf72540af8db29c5b68f406074b810 /src/lib/writer.cc | |
| parent | 2c5398adaea8bc56fe196144a9a233981657fba0 (diff) | |
Remove ref_write mechanism and instead maintain state for each
reel being written so that we don't need to keep track of frames
that are being referenced.
Diffstat (limited to 'src/lib/writer.cc')
| -rw-r--r-- | src/lib/writer.cc | 133 |
1 files changed, 62 insertions, 71 deletions
diff --git a/src/lib/writer.cc b/src/lib/writer.cc index 071cac4b6..40f4abe94 100644 --- a/src/lib/writer.cc +++ b/src/lib/writer.cc @@ -84,13 +84,10 @@ Writer::Writer (shared_ptr<const Film> film, weak_ptr<Job> j) , _thread (0) , _finish (false) , _queued_full_in_memory (0) - , _last_written_frame (-1) - , _last_written_eyes (EYES_RIGHT) , _maximum_frames_in_memory (0) , _full_written (0) , _fake_written (0) , _repeat_written (0) - , _ref_written (0) , _pushed_to_disk (0) { /* Remove any old DCP */ @@ -179,7 +176,12 @@ Writer::~Writer () terminate_thread (false); } -/** @param frame Frame within the DCP */ +/** Pass a video frame to the writer for writing to disk at some point. + * This method can be called with frames out of order. + * @param encoded JPEG2000-encoded data. + * @param frame Frame index within the DCP. + * @param eyes Eyes that this frame image is for. + */ void Writer::write (Data encoded, Frame frame, Eyes eyes) { @@ -193,7 +195,8 @@ Writer::write (Data encoded, Frame frame, Eyes eyes) QueueItem qi; qi.type = QueueItem::FULL; qi.encoded = encoded; - qi.frame = frame; + qi.reel = video_reel (frame); + qi.frame = frame - _reels[qi.reel].period.from.frames_floor (_film->video_frame_rate()); if (_film->three_d() && eyes == EYES_BOTH) { /* 2D material in a 3D DCP; fake the 3D */ @@ -213,6 +216,10 @@ Writer::write (Data encoded, Frame frame, Eyes eyes) _empty_condition.notify_all (); } +/** Repeat the last frame that was written to a reel as a new frame. + * @param frame Frame index within the DCP of the new (repeated) frame. + * @param eyes Eyes that this repeated frame image is for. + */ void Writer::repeat (Frame frame, Eyes eyes) { @@ -225,7 +232,8 @@ Writer::repeat (Frame frame, Eyes eyes) QueueItem qi; qi.type = QueueItem::REPEAT; - qi.frame = frame; + qi.reel = video_reel (frame); + qi.frame = frame - _reels[qi.reel].period.from.frames_floor (_film->video_frame_rate()); if (_film->three_d() && eyes == EYES_BOTH) { qi.eyes = EYES_LEFT; _queue.push_back (qi); @@ -250,19 +258,21 @@ Writer::fake_write (Frame frame, Eyes eyes) _full_condition.wait (lock); } - Reel const & reel = video_reel (frame); + size_t const reel = video_reel (frame); + Frame const reel_frame = frame - _reels[reel].period.from.frames_floor (_film->video_frame_rate()); - FILE* file = fopen_boost (_film->info_file(reel.period), "rb"); + FILE* file = fopen_boost (_film->info_file(_reels[reel].period), "rb"); if (!file) { - throw ReadFileError (_film->info_file(reel.period)); + throw ReadFileError (_film->info_file(_reels[reel].period)); } - dcp::FrameInfo info = read_frame_info (file, frame, eyes); + dcp::FrameInfo info = read_frame_info (file, reel_frame, eyes); fclose (file); QueueItem qi; qi.type = QueueItem::FAKE; qi.size = info.size; - qi.frame = frame; + qi.reel = reel; + qi.frame = reel_frame; if (_film->three_d() && eyes == EYES_BOTH) { qi.eyes = EYES_LEFT; _queue.push_back (qi); @@ -277,27 +287,8 @@ Writer::fake_write (Frame frame, Eyes eyes) _empty_condition.notify_all (); } -void -Writer::ref_write (Frame frame) -{ - boost::mutex::scoped_lock lock (_state_mutex); - - while (_queued_full_in_memory > _maximum_frames_in_memory) { - /* The queue is too big; wait until that is sorted out */ - _full_condition.wait (lock); - } - - QueueItem qi; - qi.type = QueueItem::REF; - qi.frame = frame; - qi.eyes = EYES_BOTH; - _queue.push_back (qi); - - /* Now there's something to do: wake anything wait()ing on _empty_condition */ - _empty_condition.notify_all (); -} - /** Write one video frame's worth of audio frames to the DCP. + * @param audio Audio data or 0 if there is no audio to be written here (i.e. it is referenced). * This method is not thread safe. */ void @@ -308,16 +299,14 @@ Writer::write (shared_ptr<const AudioBuffers> audio) } if (audio) { + DCPOMATIC_ASSERT (_audio_reel->sound_asset_writer); _audio_reel->sound_asset_writer->write (audio->data(), audio->frames()); } - ++_audio_reel->written; - - cout << "(written " << _audio_reel->written << "); period is " << _audio_reel->period.duration() << "\n"; + ++_audio_reel->total_written_audio_frames; /* written is in video frames, not audio frames */ - if (_audio_reel->written >= _audio_reel->period.duration().frames_round (_film->video_frame_rate())) { - cout << "NEXT AUDIO REEL!\n"; + if (_audio_reel->total_written_audio_frames >= _audio_reel->period.duration().frames_floor (_film->video_frame_rate())) { ++_audio_reel; } } @@ -332,30 +321,33 @@ Writer::have_sequenced_image_at_queue_head () _queue.sort (); + QueueItem const & f = _queue.front(); + Reel const & reel = _reels[f.reel]; + /* The queue should contain only EYES_LEFT/EYES_RIGHT pairs or EYES_BOTH */ - if (_queue.front().eyes == EYES_BOTH) { + if (f.eyes == EYES_BOTH) { /* 2D */ - return _queue.front().frame == (_last_written_frame + 1); + return f.frame == (reel.last_written_video_frame + 1); } /* 3D */ - if (_last_written_eyes == EYES_LEFT && _queue.front().frame == _last_written_frame && _queue.front().eyes == EYES_RIGHT) { + if (reel.last_written_eyes == EYES_LEFT && f.frame == reel.last_written_video_frame && f.eyes == EYES_RIGHT) { return true; } - if (_last_written_eyes == EYES_RIGHT && _queue.front().frame == (_last_written_frame + 1) && _queue.front().eyes == EYES_LEFT) { + if (reel.last_written_eyes == EYES_RIGHT && f.frame == (reel.last_written_video_frame + 1) && f.eyes == EYES_LEFT) { return true; } return false; } +/** @param frame reel-relative frame */ void -Writer::write_frame_info (int frame, Eyes eyes, dcp::FrameInfo info) const +Writer::write_frame_info (Reel const & reel, int frame, Eyes eyes, dcp::FrameInfo info) const { - Reel const & reel = video_reel (frame); FILE* file = 0; boost::filesystem::path info_file = _film->info_file (reel.period); if (boost::filesystem::exists (info_file)) { @@ -414,10 +406,10 @@ try LOG_WARNING (N_("- type FAKE, size %1, frame %2, eyes %3"), i->size, i->frame, i->eyes); } } - LOG_WARNING (N_("Last written frame %1, last written eyes %2"), _last_written_frame, _last_written_eyes); } return; } + /* Write any frames that we can write; i.e. those that are in sequence. */ while (have_sequenced_image_at_queue_head ()) { QueueItem qi = _queue.front (); @@ -428,19 +420,19 @@ try lock.unlock (); - Reel const & reel = video_reel (qi.frame); + Reel& reel = _reels[qi.reel]; switch (qi.type) { case QueueItem::FULL: { LOG_DEBUG_ENCODE (N_("Writer FULL-writes %1 (%2)"), qi.frame, qi.eyes); if (!qi.encoded) { - qi.encoded = Data (_film->j2c_path (qi.frame, qi.eyes, false)); + qi.encoded = Data (_film->j2c_path (qi.reel, qi.frame, qi.eyes, false)); } dcp::FrameInfo fin = reel.picture_asset_writer->write (qi.encoded->data().get (), qi.encoded->size()); - write_frame_info (qi.frame, qi.eyes, fin); - _last_written[qi.eyes] = qi.encoded; + write_frame_info (reel, qi.frame, qi.eyes, fin); + reel.last_written[qi.eyes] = qi.encoded; ++_full_written; break; } @@ -453,23 +445,19 @@ try { LOG_DEBUG_ENCODE (N_("Writer REPEAT-writes %1"), qi.frame); dcp::FrameInfo fin = reel.picture_asset_writer->write ( - _last_written[qi.eyes]->data().get(), - _last_written[qi.eyes]->size() + reel.last_written[qi.eyes]->data().get(), + reel.last_written[qi.eyes]->size() ); - write_frame_info (qi.frame, qi.eyes, fin); + write_frame_info (reel, qi.frame, qi.eyes, fin); ++_repeat_written; break; } - case QueueItem::REF: - LOG_DEBUG_ENCODE (N_("Writer REF-writes %1"), qi.frame); - ++_ref_written; - break; } lock.lock (); - _last_written_frame = qi.frame; - _last_written_eyes = qi.eyes; + reel.last_written_video_frame = qi.frame; + reel.last_written_eyes = qi.eyes; shared_ptr<Job> job = _job.lock (); DCPOMATIC_ASSERT (job); @@ -481,7 +469,7 @@ try total *= 2; } if (total) { - job->set_progress (float (_full_written + _fake_written + _repeat_written + _ref_written) / total); + job->set_progress (float (_full_written + _fake_written + _repeat_written) / total); } } @@ -506,13 +494,12 @@ try thread could erase the last item in the list. */ - LOG_GENERAL ( - "Writer full (awaiting %1 [last eye was %2]); pushes %3 to disk", - _last_written_frame + 1, - _last_written_eyes, i->frame - ); + LOG_GENERAL ("Writer full; pushes %1 to disk", i->frame); - i->encoded->write_via_temp (_film->j2c_path (i->frame, i->eyes, true), _film->j2c_path (i->frame, i->eyes, false)); + i->encoded->write_via_temp ( + _film->j2c_path (i->reel, i->frame, i->eyes, true), + _film->j2c_path (i->reel, i->frame, i->eyes, false) + ); lock.lock (); i->encoded.reset (); @@ -757,7 +744,7 @@ Writer::finish () dcp.write_xml (_film->interop () ? dcp::INTEROP : dcp::SMPTE, meta, signer); LOG_GENERAL ( - N_("Wrote %1 FULL, %2 FAKE, %3 REPEAT, %4 REF, %5 pushed to disk"), _full_written, _fake_written, _repeat_written, _ref_written, _pushed_to_disk + N_("Wrote %1 FULL, %2 FAKE, %3 REPEAT, %4 pushed to disk"), _full_written, _fake_written, _repeat_written, _pushed_to_disk ); } @@ -840,7 +827,7 @@ Writer::can_fake_write (Frame frame) const parameters in the asset writer. */ - Reel const & reel = video_reel (frame); + Reel const & reel = _reels[video_reel(frame)]; /* Make frame relative to the start of the reel */ frame -= reel.period.from.frames_floor (_film->video_frame_rate()); @@ -896,6 +883,10 @@ Writer::write (list<shared_ptr<Font> > fonts) bool operator< (QueueItem const & a, QueueItem const & b) { + if (a.reel != b.reel) { + return a.reel < b.reel; + } + if (a.frame != b.frame) { return a.frame < b.frame; } @@ -906,7 +897,7 @@ operator< (QueueItem const & a, QueueItem const & b) bool operator== (QueueItem const & a, QueueItem const & b) { - return a.frame == b.frame && a.eyes == b.eyes; + return a.reel == b.reel && a.frame == b.frame && a.eyes == b.eyes; } void @@ -954,15 +945,15 @@ Writer::write (ReferencedReelAsset asset) _reel_assets.push_back (asset); } -Writer::Reel const & +size_t Writer::video_reel (int frame) const { DCPTime t = DCPTime::from_frames (frame, _film->video_frame_rate ()); - list<Reel>::const_iterator i = _reels.begin (); - while (i != _reels.end() && !i->period.contains (t)) { + size_t i = 0; + while (i < _reels.size() && !_reels[i].period.contains (t)) { ++i; } - DCPOMATIC_ASSERT (i != _reels.end ()); - return *i; + DCPOMATIC_ASSERT (i < _reels.size ()); + return i; } |
