Store video frame rate in XML (#883).
authorCarl Hetherington <cth@carlh.net>
Wed, 1 Jun 2016 21:45:58 +0000 (22:45 +0100)
committerCarl Hetherington <cth@carlh.net>
Wed, 1 Jun 2016 21:45:58 +0000 (22:45 +0100)
src/lib/content.cc
src/lib/frame_rate_change.cc
src/lib/types.h

index 7afbf924f63912c5631caf1a8b138583ad3ca616..66b0d477e7f92aa2df87db3e8c2e521ce2a4e98c 100644 (file)
@@ -95,6 +95,7 @@ Content::Content (shared_ptr<const Film> film, cxml::ConstNodePtr node)
        _position = DCPTime (node->number_child<DCPTime::Type> ("Position"));
        _trim_start = ContentTime (node->number_child<ContentTime::Type> ("TrimStart"));
        _trim_end = ContentTime (node->number_child<ContentTime::Type> ("TrimEnd"));
+       _video_frame_rate = node->optional_number_child<double> ("VideoFrameRate");
 }
 
 Content::Content (shared_ptr<const Film> film, vector<shared_ptr<Content> > c)
@@ -102,6 +103,7 @@ Content::Content (shared_ptr<const Film> film, vector<shared_ptr<Content> > c)
        , _position (c.front()->position ())
        , _trim_start (c.front()->trim_start ())
        , _trim_end (c.back()->trim_end ())
+       , _video_frame_rate (c.front()->video_frame_rate())
        , _change_signals_frequent (false)
 {
        for (size_t i = 0; i < c.size(); ++i) {
@@ -113,6 +115,17 @@ Content::Content (shared_ptr<const Film> film, vector<shared_ptr<Content> > c)
                        throw JoinError (_("Only the last piece of content to be joined can have an end trim."));
                }
 
+               if (
+                       (_video_frame_rate && !c[i]->_video_frame_rate) ||
+                       (!_video_frame_rate && c[i]->_video_frame_rate)
+                       ) {
+                       throw JoinError (_("Content to be joined must have the same video frame rate"));
+               }
+
+               if (_video_frame_rate && fabs (_video_frame_rate.get() - c[i]->_video_frame_rate.get()) > VIDEO_FRAME_RATE_EPSILON) {
+                       throw JoinError (_("Content to be joined must have the same video frame rate"));
+               }
+
                for (size_t j = 0; j < c[i]->number_of_paths(); ++j) {
                        _paths.push_back (c[i]->path (j));
                }
@@ -131,6 +144,9 @@ Content::as_xml (xmlpp::Node* node) const
        node->add_child("Position")->add_child_text (raw_convert<string> (_position.get ()));
        node->add_child("TrimStart")->add_child_text (raw_convert<string> (_trim_start.get ()));
        node->add_child("TrimEnd")->add_child_text (raw_convert<string> (_trim_end.get ()));
+       if (_video_frame_rate) {
+               node->add_child("VideoFrameRate")->add_child_text (raw_convert<string> (_video_frame_rate.get()));
+       }
 }
 
 void
index 8b2d6cf99c54411d95008f0bc2d29835000d6dec..80a167029009349913b21e15c35d6aa0c760b4f2 100644 (file)
@@ -1,5 +1,5 @@
 /*
-    Copyright (C) 2012-2015 Carl Hetherington <cth@carlh.net>
+    Copyright (C) 2012-2016 Carl Hetherington <cth@carlh.net>
 
     This file is part of DCP-o-matic.
 
 
 */
 
-#include <cmath>
 #include "frame_rate_change.h"
+#include "types.h"
 #include "compose.hpp"
+#include <cmath>
 
 #include "i18n.h"
 
@@ -29,28 +30,7 @@ using std::string;
 static bool
 about_equal (double a, double 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);
+       return (fabs (a - b) < VIDEO_FRAME_RATE_EPSILON);
 }
 
 
index d9bee97c6b910a55683b5bfde474a362f8396a1c..ab51e38a9d7a1f8dabd3f749847928b36450bdf9 100644 (file)
@@ -48,6 +48,28 @@ namespace xmlpp {
  */
 #define SERVER_LINK_VERSION (64+0)
 
+/** 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 ~= 1e-4
+*/
+#define VIDEO_FRAME_RATE_EPSILON (1e-4)
+
 typedef std::vector<boost::shared_ptr<Content> > ContentList;
 typedef std::vector<boost::shared_ptr<FFmpegContent> > FFmpegContentList;