+2014-03-03 Carl Hetherington <cth@carlh.net>
+
+ * Fix rounding of timecodes in at least some cases (#323).
+
+ * Try to prevent OS X from sleeping during DCP encode.
+
2014-02-26 Carl Hetherington <cth@carlh.net>
* Version 1.64.17 released.
.PHONY: override_dh_strip
override_dh_strip:
- dh_strip --dbg-package=dcpomatic-dbg
+ dh_strip
#ifdef DCPOMATIC_OSX
#include <sys/sysctl.h>
#include <mach-o/dyld.h>
+#include <IOKit/pwr_mgt/IOPMLib.h>
#endif
#ifdef DCPOMATIC_POSIX
#include <sys/types.h>
}
void
-kick ()
+Waker::nudge ()
{
#ifdef DCPOMATIC_WINDOWS
SetThreadExecutionState (ES_CONTINUOUS);
#endif
}
+
+Waker::Waker ()
+{
+#ifdef DCPOMATIC_OSX
+ IOPMAssertionCreateWithName (kIOPMAssertionTypeNoIdleSleep, kIOPMAssertionLevelOn, CFSTR ("Encoding DCP"), &_assertion_id);
+#endif
+}
+
+Waker::~Waker ()
+{
+#ifdef DCPOMATIC_OSX
+ IOPMAssertionRelease (_assertion_id);
+#endif
+}
*/
+#ifndef DCPOMATIC_CROSS_H
+#define DCPOMATIC_CROSS_H
+
#include <boost/filesystem.hpp>
+#ifdef DCPOMATIC_OSX
+#include <IOKit/pwr_mgt/IOPMLib.h>
+#endif
#ifdef DCPOMATIC_WINDOWS
#define WEXITSTATUS(w) (w)
#endif
extern FILE * fopen_boost (boost::filesystem::path, std::string);
extern int dcpomatic_fseek (FILE *, int64_t, int);
-void kick ();
+
+/** A class which tries to keep the computer awake on various operating systems.
+ * Create a Waker to prevent sleep, and call ::nudge every so often (every minute or so).
+ * Destroy the Waker to allow sleep again.
+ */
+class Waker
+{
+public:
+ Waker ();
+ ~Waker ();
+
+ void nudge ();
+
+private:
+#ifdef DCPOMATIC_OSX
+ IOPMAssertionID _assertion_id;
+#endif
+};
+
+#endif
void
Encoder::process_video (shared_ptr<PlayerImage> image, Eyes eyes, ColourConversion conversion, bool same)
{
- kick ();
+ _waker.nudge ();
boost::mutex::scoped_lock lock (_mutex);
}
#include "util.h"
#include "config.h"
+#include "cross.h"
class Image;
class AudioBuffers;
boost::condition _condition;
boost::shared_ptr<Writer> _writer;
+ Waker _waker;
};
#endif
AudioFrame
Film::time_to_audio_frames (DCPTime t) const
{
- return t * audio_frame_rate () / TIME_HZ;
+ return divide_with_round (t * audio_frame_rate (), TIME_HZ);
}
VideoFrame
Film::time_to_video_frames (DCPTime t) const
{
- return t * video_frame_rate () / TIME_HZ;
+ return divide_with_round (t * video_frame_rate (), TIME_HZ);
}
DCPTime
Film::audio_frames_to_time (AudioFrame f) const
{
- return f * TIME_HZ / audio_frame_rate ();
+ return divide_with_round (f * TIME_HZ, audio_frame_rate ());
}
DCPTime
Film::video_frames_to_time (VideoFrame f) const
{
- return f * TIME_HZ / video_frame_rate ();
+ return divide_with_round (f * TIME_HZ, video_frame_rate ());
}
AudioFrame
shared_ptr<const Film> film = _film.lock ();
assert (film);
- AudioFrame const len = audio_length() * output_audio_frame_rate() / content_audio_frame_rate ();
+ AudioFrame const len = divide_with_round (audio_length() * output_audio_frame_rate(), content_audio_frame_rate ());
/* XXX: this depends on whether, alongside this audio, we are running video slower or faster than
it should be. The calculation above works out the output audio frames assuming that we are just
boost::algorithm::replace_all (e, "%2F", "/");
return e;
}
+
+int64_t
+divide_with_round (int64_t a, int64_t b)
+{
+ if (a % b >= (b / 2)) {
+ return (a + b - 1) / b;
+ } else {
+ return a / b;
+ }
+}
extern int get_optional_int (std::multimap<std::string, std::string> const & kv, std::string k);
extern std::string get_optional_string (std::multimap<std::string, std::string> const & kv, std::string k);
extern void* wrapped_av_malloc (size_t);
+extern int64_t divide_with_round (int64_t a, int64_t b);
/** @class Socket
* @brief A class to wrap a boost::asio::ip::tcp::socket with some things
_seconds = new wxTextCtrl (_editable, wxID_ANY, wxT(""), wxDefaultPosition, size, 0, validator);
_seconds->SetMaxLength (2);
editable_sizer->Add (_seconds);
- add_label_to_sizer (editable_sizer, _editable, wxT ("."), false);
+ add_label_to_sizer (editable_sizer, _editable, wxT (":"), false);
_frames = new wxTextCtrl (_editable, wxID_ANY, wxT(""), wxDefaultPosition, size, 0, validator);
_frames->SetMaxLength (2);
editable_sizer->Add (_frames);
t -= m * 60 * TIME_HZ;
int const s = t / TIME_HZ;
t -= s * TIME_HZ;
- int const f = t * fps / TIME_HZ;
+ int const f = divide_with_round (t * fps, TIME_HZ);
checked_set (_hours, lexical_cast<string> (h));
checked_set (_minutes, lexical_cast<string> (m));
using std::vector;
using boost::shared_ptr;
-BOOST_AUTO_TEST_CASE (util_test)
+BOOST_AUTO_TEST_CASE (split_at_spaces_considering_quotes_test)
{
string t = "Hello this is a string \"with quotes\" and indeed without them";
vector<string> b = split_at_spaces_considering_quotes (t);
BOOST_CHECK_EQUAL (time_round_up (42, 42), 42);
BOOST_CHECK_EQUAL (time_round_up (43, 42), 84);
}
+
+
+BOOST_AUTO_TEST_CASE (divide_with_round_test)
+{
+ BOOST_CHECK_EQUAL (divide_with_round (0, 4), 0);
+ BOOST_CHECK_EQUAL (divide_with_round (1, 4), 0);
+ BOOST_CHECK_EQUAL (divide_with_round (2, 4), 1);
+ BOOST_CHECK_EQUAL (divide_with_round (3, 4), 1);
+ BOOST_CHECK_EQUAL (divide_with_round (4, 4), 1);
+ BOOST_CHECK_EQUAL (divide_with_round (5, 4), 1);
+ BOOST_CHECK_EQUAL (divide_with_round (6, 4), 2);
+
+ BOOST_CHECK_EQUAL (divide_with_round (1000, 500), 2);
+}