summaryrefslogtreecommitdiff
path: root/src/lib
diff options
context:
space:
mode:
authorCarl Hetherington <cth@carlh.net>2014-06-04 13:10:28 +0100
committerCarl Hetherington <cth@carlh.net>2014-06-04 13:10:28 +0100
commit4a74ca2cb973585122e84c21ff48ff4ff1ebd488 (patch)
treee73cc4ef0850326f1f45037b0c22ab00a0f94685 /src/lib
parent418f17235e05d5f8c449e848c6a81e1b9017bd8a (diff)
Back-port v2's rename and slight extension of FrameRateConversion.
Diffstat (limited to 'src/lib')
-rw-r--r--src/lib/audio_content.cc5
-rw-r--r--src/lib/ffmpeg_content.cc3
-rw-r--r--src/lib/frame_rate_change.cc91
-rw-r--r--src/lib/frame_rate_change.h58
-rw-r--r--src/lib/image_content.cc3
-rw-r--r--src/lib/player.cc3
-rw-r--r--src/lib/util.cc38
-rw-r--r--src/lib/util.h34
-rw-r--r--src/lib/video_content.cc3
-rw-r--r--src/lib/wscript1
10 files changed, 161 insertions, 78 deletions
diff --git a/src/lib/audio_content.cc b/src/lib/audio_content.cc
index 79912f1ae..7d77154e1 100644
--- a/src/lib/audio_content.cc
+++ b/src/lib/audio_content.cc
@@ -25,6 +25,7 @@
#include "film.h"
#include "exceptions.h"
#include "config.h"
+#include "frame_rate_change.h"
#include "i18n.h"
@@ -159,7 +160,7 @@ AudioContent::output_audio_frame_rate () const
/* Resample to a DCI-approved sample rate */
double t = dcp_audio_frame_rate (content_audio_frame_rate ());
- FrameRateConversion frc (video_frame_rate(), film->video_frame_rate());
+ FrameRateChange frc (video_frame_rate(), film->video_frame_rate());
/* Compensate if the DCP is being run at a different frame rate
to the source; that is, if the video is run such that it will
@@ -168,7 +169,7 @@ AudioContent::output_audio_frame_rate () const
*/
if (frc.change_speed) {
- t *= video_frame_rate() * frc.factor() / film->video_frame_rate();
+ t /= frc.speed_up;
}
return rint (t);
diff --git a/src/lib/ffmpeg_content.cc b/src/lib/ffmpeg_content.cc
index 4ea6dbc6a..4d886a6dd 100644
--- a/src/lib/ffmpeg_content.cc
+++ b/src/lib/ffmpeg_content.cc
@@ -31,6 +31,7 @@ extern "C" {
#include "film.h"
#include "log.h"
#include "exceptions.h"
+#include "frame_rate_change.h"
#include "i18n.h"
@@ -407,7 +408,7 @@ FFmpegContent::full_length () const
shared_ptr<const Film> film = _film.lock ();
assert (film);
- FrameRateConversion frc (video_frame_rate (), film->video_frame_rate ());
+ FrameRateChange frc (video_frame_rate (), film->video_frame_rate ());
return video_length_after_3d_combine() * frc.factor() * TIME_HZ / film->video_frame_rate ();
}
diff --git a/src/lib/frame_rate_change.cc b/src/lib/frame_rate_change.cc
new file mode 100644
index 000000000..3e9c4b505
--- /dev/null
+++ b/src/lib/frame_rate_change.cc
@@ -0,0 +1,91 @@
+/*
+ Copyright (C) 2012-2014 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 <cmath>
+#include "frame_rate_change.h"
+#include "compose.hpp"
+
+#include "i18n.h"
+
+static bool
+about_equal (float a, float b)
+{
+ /* A film of F seconds at f FPS will be Ff frames;
+ Consider some delta FPS d, so if we run the same
+ film at (f + d) FPS it will last F(f + d) seconds.
+
+ Hence the difference in length over the length of the film will
+ be F(f + d) - Ff frames
+ = Ff + Fd - Ff frames
+ = Fd frames
+ = Fd/f seconds
+
+ So if we accept a difference of 1 frame, ie 1/f seconds, we can
+ say that
+
+ 1/f = Fd/f
+ ie 1 = Fd
+ ie d = 1/F
+
+ So for a 3hr film, ie F = 3 * 60 * 60 = 10800, the acceptable
+ FPS error is 1/F ~= 0.0001 ~= 10-e4
+ */
+
+ return (fabs (a - b) < 1e-4);
+}
+
+
+FrameRateChange::FrameRateChange (float source, int dcp)
+ : skip (false)
+ , repeat (1)
+ , change_speed (false)
+{
+ if (fabs (source / 2.0 - dcp) < fabs (source - dcp)) {
+ /* The difference between source and DCP frame rate will be lower
+ (i.e. better) if we skip.
+ */
+ skip = true;
+ } else if (fabs (source * 2 - dcp) < fabs (source - dcp)) {
+ /* The difference between source and DCP frame rate would be better
+ if we repeated each frame once; it may be better still if we
+ repeated more than once. Work out the required repeat.
+ */
+ repeat = round (dcp / source);
+ }
+
+ speed_up = dcp / (source * factor());
+ change_speed = !about_equal (speed_up, 1.0);
+
+ if (!skip && repeat == 1 && !change_speed) {
+ description = _("Content and DCP have the same rate.\n");
+ } else {
+ if (skip) {
+ description = _("DCP will use every other frame of the content.\n");
+ } else if (repeat == 2) {
+ description = _("Each content frame will be doubled in the DCP.\n");
+ } else if (repeat > 2) {
+ description = String::compose (_("Each content frame will be repeated %1 more times in the DCP.\n"), repeat - 1);
+ }
+
+ if (change_speed) {
+ float const pc = dcp * 100 / (source * factor());
+ description += String::compose (_("DCP will run at %1%% of the content speed.\n"), pc);
+ }
+ }
+}
diff --git a/src/lib/frame_rate_change.h b/src/lib/frame_rate_change.h
new file mode 100644
index 000000000..6165f6840
--- /dev/null
+++ b/src/lib/frame_rate_change.h
@@ -0,0 +1,58 @@
+/*
+ Copyright (C) 2012-2014 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 <string>
+
+struct FrameRateChange
+{
+ FrameRateChange (float, int);
+
+ /** @return factor by which to multiply a source frame rate
+ to get the effective rate after any skip or repeat has happened.
+ */
+ float factor () const {
+ if (skip) {
+ return 0.5;
+ }
+
+ return repeat;
+ }
+
+ /** true to skip every other frame */
+ bool skip;
+ /** number of times to use each frame (e.g. 1 is normal, 2 means repeat each frame once, and so on) */
+ int repeat;
+ /** true if this DCP will run its video faster or slower than the source
+ * without taking into account `repeat' nor `skip'.
+ * (e.g. change_speed will be true if
+ * source is 29.97fps, DCP is 30fps
+ * source is 14.50fps, DCP is 30fps
+ * but not if
+ * source is 15.00fps, DCP is 30fps
+ * source is 12.50fps, DCP is 25fps)
+ */
+ bool change_speed;
+
+ /** Amount by which the video is being sped-up in the DCP; e.g. for a
+ * 24fps source in a 25fps DCP this would be 25/24.
+ */
+ float speed_up;
+
+ std::string description;
+};
diff --git a/src/lib/image_content.cc b/src/lib/image_content.cc
index 3b87fcf00..6acf0bab9 100644
--- a/src/lib/image_content.cc
+++ b/src/lib/image_content.cc
@@ -24,6 +24,7 @@
#include "compose.hpp"
#include "film.h"
#include "job.h"
+#include "frame_rate_change.h"
#include "i18n.h"
@@ -130,7 +131,7 @@ ImageContent::full_length () const
shared_ptr<const Film> film = _film.lock ();
assert (film);
- FrameRateConversion frc (video_frame_rate(), film->video_frame_rate ());
+ FrameRateChange frc (video_frame_rate(), film->video_frame_rate ());
return video_length_after_3d_combine() * frc.factor() * TIME_HZ / video_frame_rate();
}
diff --git a/src/lib/player.cc b/src/lib/player.cc
index 68df8ea70..20cea7e4a 100644
--- a/src/lib/player.cc
+++ b/src/lib/player.cc
@@ -36,6 +36,7 @@
#include "log.h"
#include "scaler.h"
#include "player_video_frame.h"
+#include "frame_rate_change.h"
#define LOG_GENERAL(...) _film->log()->log (String::compose (__VA_ARGS__), Log::TYPE_GENERAL);
@@ -201,7 +202,7 @@ Player::process_video (weak_ptr<Piece> weak_piece, shared_ptr<const ImageProxy>
shared_ptr<VideoContent> content = dynamic_pointer_cast<VideoContent> (piece->content);
assert (content);
- FrameRateConversion frc (content->video_frame_rate(), _film->video_frame_rate());
+ FrameRateChange frc (content->video_frame_rate(), _film->video_frame_rate());
if (frc.skip && (frame % 2) == 1) {
return;
}
diff --git a/src/lib/util.cc b/src/lib/util.cc
index bbe6f77e1..fa7be179a 100644
--- a/src/lib/util.cc
+++ b/src/lib/util.cc
@@ -789,44 +789,6 @@ audio_channel_name (int c)
return channels[c];
}
-FrameRateConversion::FrameRateConversion (float source, int dcp)
- : skip (false)
- , repeat (1)
- , change_speed (false)
-{
- if (fabs (source / 2.0 - dcp) < fabs (source - dcp)) {
- /* The difference between source and DCP frame rate will be lower
- (i.e. better) if we skip.
- */
- skip = true;
- } else if (fabs (source * 2 - dcp) < fabs (source - dcp)) {
- /* The difference between source and DCP frame rate would be better
- if we repeated each frame once; it may be better still if we
- repeated more than once. Work out the required repeat.
- */
- repeat = round (dcp / source);
- }
-
- change_speed = !about_equal (source * factor(), dcp);
-
- if (!skip && repeat == 1 && !change_speed) {
- description = _("Content and DCP have the same rate.\n");
- } else {
- if (skip) {
- description = _("DCP will use every other frame of the content.\n");
- } else if (repeat == 2) {
- description = _("Each content frame will be doubled in the DCP.\n");
- } else if (repeat > 2) {
- description = String::compose (_("Each content frame will be repeated %1 more times in the DCP.\n"), repeat - 1);
- }
-
- if (change_speed) {
- float const pc = dcp * 100 / (source * factor());
- description += String::compose (_("DCP will run at %1%% of the content speed.\n"), pc);
- }
- }
-}
-
bool
valid_image_file (boost::filesystem::path f)
{
diff --git a/src/lib/util.h b/src/lib/util.h
index 5d93456df..70bf495c6 100644
--- a/src/lib/util.h
+++ b/src/lib/util.h
@@ -73,40 +73,6 @@ extern boost::shared_ptr<const libdcp::Signer> make_signer ();
extern libdcp::Size fit_ratio_within (float ratio, libdcp::Size);
extern std::string entities_to_text (std::string e);
extern std::map<std::string, std::string> split_get_request (std::string url);
-
-struct FrameRateConversion
-{
- FrameRateConversion (float, int);
-
- /** @return factor by which to multiply a source frame rate
- to get the effective rate after any skip or repeat has happened.
- */
- float factor () const {
- if (skip) {
- return 0.5;
- }
-
- return repeat;
- }
-
- /** true to skip every other frame */
- bool skip;
- /** number of times to use each frame (e.g. 1 is normal, 2 means repeat each frame once, and so on) */
- int repeat;
- /** true if this DCP will run its video faster or slower than the source
- * without taking into account `repeat' nor `skip'.
- * (e.g. change_speed will be true if
- * source is 29.97fps, DCP is 30fps
- * source is 14.50fps, DCP is 30fps
- * but not if
- * source is 15.00fps, DCP is 30fps
- * source is 12.50fps, DCP is 25fps)
- */
- bool change_speed;
-
- std::string description;
-};
-
extern int dcp_audio_frame_rate (int);
extern int stride_round_up (int, int const *, int);
extern std::multimap<std::string, std::string> read_key_value (std::istream& s);
diff --git a/src/lib/video_content.cc b/src/lib/video_content.cc
index 40772980f..ec5890b45 100644
--- a/src/lib/video_content.cc
+++ b/src/lib/video_content.cc
@@ -30,6 +30,7 @@
#include "util.h"
#include "film.h"
#include "exceptions.h"
+#include "frame_rate_change.h"
#include "i18n.h"
@@ -367,7 +368,7 @@ VideoContent::time_to_content_video_frames (Time t) const
shared_ptr<const Film> film = _film.lock ();
assert (film);
- FrameRateConversion frc (video_frame_rate(), film->video_frame_rate());
+ FrameRateChange frc (video_frame_rate(), film->video_frame_rate());
/* Here we are converting from time (in the DCP) to a frame number in the content.
Hence we need to use the DCP's frame rate and the double/skip correction, not
diff --git a/src/lib/wscript b/src/lib/wscript
index f932a142d..517ad7787 100644
--- a/src/lib/wscript
+++ b/src/lib/wscript
@@ -30,6 +30,7 @@ sources = """
ffmpeg_examiner.cc
film.cc
filter.cc
+ frame_rate_change.cc
internet.cc
image.cc
image_content.cc