{
boost::mutex::scoped_lock lock (_mutex);
+ /* XXX: discard 3D here if required */
+
/* Wait until the queue has gone down a bit */
while (_queue.size() >= _threads.size() * 2 && !_terminate) {
TIMING ("decoder sleeps with queue of %1", _queue.size());
_have_a_real_frame[eyes] = true;
}
- ++_video_frames_out;
+ if (eyes != EYES_LEFT) {
+ ++_video_frames_out;
+ }
}
void
TIMING ("encoder thread %1 wakes with queue of %2", boost::this_thread::get_id(), _queue.size());
shared_ptr<DCPVideoFrame> vf = _queue.front ();
- _film->log()->log (String::compose (N_("Encoder thread %1 pops frame %2 from queue"), boost::this_thread::get_id(), vf->frame()), Log::VERBOSE);
+ _film->log()->log (String::compose (N_("Encoder thread %1 pops frame %2 (%3) from queue"), boost::this_thread::get_id(), vf->frame(), vf->eyes ()));
_queue.pop_front ();
lock.unlock ();
, _finish (false)
, _queued_full_in_memory (0)
, _last_written_frame (-1)
+ , _last_written_eyes (EYES_RIGHT)
, _full_written (0)
, _fake_written (0)
, _repeat_written (0)
qi.type = QueueItem::FULL;
qi.encoded = encoded;
qi.frame = frame;
- qi.eyes = eyes;
- _queue.push_back (qi);
- ++_queued_full_in_memory;
+ if (_film->dcp_3d() && eyes == EYES_BOTH) {
+ /* 2D material in a 3D DCP; fake the 3D */
+ qi.eyes = EYES_LEFT;
+ _queue.push_back (qi);
+ ++_queued_full_in_memory;
+ qi.eyes = EYES_RIGHT;
+ _queue.push_back (qi);
+ ++_queued_full_in_memory;
+ } else {
+ qi.eyes = eyes;
+ _queue.push_back (qi);
+ ++_queued_full_in_memory;
+ }
+
_condition.notify_all ();
}
_sound_asset_writer->write (audio->data(), audio->frames());
}
-/** This must be called from Writer::thread() with an appropriate lock held */
+/** This must be called from Writer::thread() with an appropriate lock held,
+ * and with _queue sorted.
+ */
bool
Writer::have_sequenced_image_at_queue_head () const
{
return false;
}
- /* We assume that we will get either all 2D frames or all 3D frames, not a mixture */
-
- bool const eyes_ok = (_queue.front().eyes == EYES_BOTH) ||
- (_queue.front().eyes == EYES_LEFT && _last_written_eyes == EYES_RIGHT) ||
- (_queue.front().eyes == EYES_RIGHT && _last_written_eyes == EYES_LEFT);
-
- return _queue.front().frame == (_last_written_frame + 1) && eyes_ok;
+ /* The queue should contain only EYES_LEFT/EYES_RIGHT pairs or EYES_BOTH */
+
+ if (_queue.front().eyes == EYES_BOTH) {
+ /* 2D */
+ return _queue.front().frame == (_last_written_frame + 1);
+ }
+
+ /* 3D */
+
+ if (_last_written_eyes == EYES_LEFT && _queue.front().frame == _last_written_frame && _queue.front().eyes == EYES_RIGHT) {
+ return true;
+ }
+
+ if (_last_written_eyes == EYES_RIGHT && _queue.front().frame == (_last_written_frame + 1) && _queue.front().eyes == EYES_LEFT) {
+ return true;
+ }
+
+ return false;
}
void
if (_finish || _queued_full_in_memory > _maximum_frames_in_memory || have_sequenced_image_at_queue_head ()) {
break;
}
-
+
TIMING (N_("writer sleeps with a queue of %1"), _queue.size());
_condition.wait (lock);
TIMING (N_("writer wakes with a queue of %1"), _queue.size());
if (_mono_picture_asset_writer) {
libdcp::FrameInfo fin = _mono_picture_asset_writer->write (
- _last_written[EYES_BOTH]->data(),
- _last_written[EYES_BOTH]->size()
+ _last_written[qi.eyes]->data(),
+ _last_written[qi.eyes]->size()
);
- _last_written[EYES_BOTH]->write_info (_film, qi.frame, qi.eyes, fin);
+ _last_written[qi.eyes]->write_info (_film, qi.frame, qi.eyes, fin);
} else {
libdcp::FrameInfo fin = _stereo_picture_asset_writer->write (
- _last_written[EYES_LEFT]->data(), _last_written[EYES_LEFT]->size(), libdcp::EYE_LEFT
+ _last_written[qi.eyes]->data(),
+ _last_written[qi.eyes]->size(),
+ qi.eyes == EYES_LEFT ? libdcp::EYE_LEFT : libdcp::EYE_RIGHT
);
- _last_written[EYES_LEFT]->write_info (_film, qi.frame, qi.eyes, fin);
-
- fin = _stereo_picture_asset_writer->write (
- _last_written[EYES_RIGHT]->data(), _last_written[EYES_RIGHT]->size(), libdcp::EYE_RIGHT
- );
-
- _last_written[EYES_RIGHT]->write_info (_film, qi.frame, qi.eyes, fin);
+ _last_written[qi.eyes]->write_info (_film, qi.frame, qi.eyes, fin);
}
++_repeat_written;
}
}
lock.lock ();
+
+ _last_written_frame = qi.frame;
+ _last_written_eyes = qi.eyes;
if (_film->length()) {
_job->set_progress (
float (_full_written + _fake_written + _repeat_written) / _film->time_to_video_frames (_film->length())
);
}
-
- ++_last_written_frame;
}
while (_queued_full_in_memory > _maximum_frames_in_memory) {
++_pushed_to_disk;
lock.unlock ();
- _film->log()->log (String::compose (N_("Writer full (awaiting %1); pushes %2 to disk"), _last_written_frame + 1, qi.frame));
+
+ _film->log()->log (
+ String::compose (
+ "Writer full (awaiting %1 [last eye was %2]); pushes %3 to disk",
+ _last_written_frame + 1,
+ _last_written_eyes, qi.frame)
+ );
+
qi.encoded->write (_film, qi.frame, qi.eyes);
lock.lock ();
qi.encoded.reset ();
--- /dev/null
+/*
+ Copyright (C) 2013 Carl Hetherington <cth@carlh.net>
+
+ This program 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.
+
+ This program 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 this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+*/
+
+#include <boost/test/unit_test.hpp>
+#include "test.h"
+#include "lib/film.h"
+#include "lib/ratio.h"
+#include "lib/dcp_content_type.h"
+#include "lib/ffmpeg_content.h"
+
+using std::cout;
+using boost::shared_ptr;
+
+BOOST_AUTO_TEST_CASE (threed_test)
+{
+ cout << "here we go.\n";
+ shared_ptr<Film> film = new_test_film ("threed_test");
+ film->set_name ("test_film2");
+ shared_ptr<FFmpegContent> c (new FFmpegContent (film, "test/data/test.mp4"));
+ c->set_ratio (Ratio::from_id ("185"));
+ c->set_video_frame_type (VIDEO_FRAME_TYPE_3D_LEFT_RIGHT);
+ film->examine_and_add_content (c);
+
+ wait_for_jobs ();
+
+ film->set_container (Ratio::from_id ("185"));
+ film->set_dcp_content_type (DCPContentType::from_pretty_name ("Test"));
+ film->set_dcp_3d (true);
+ film->make_dcp ();
+ film->write_metadata ();
+
+ wait_for_jobs ();
+
+ exit (EXIT_SUCCESS);
+}