Mostly-merge master.
authorCarl Hetherington <cth@carlh.net>
Fri, 21 Mar 2014 12:36:17 +0000 (12:36 +0000)
committerCarl Hetherington <cth@carlh.net>
Fri, 21 Mar 2014 12:36:17 +0000 (12:36 +0000)
16 files changed:
1  2 
ChangeLog
cscript
src/lib/ffmpeg.cc
src/lib/ffmpeg_content.cc
src/lib/ffmpeg_decoder.h
src/lib/image.cc
src/lib/image_content.cc
src/lib/types.h
src/lib/util.cc
src/lib/video_content.cc
src/lib/video_content.h
src/lib/video_decoder.cc
src/wx/timecode.cc
src/wx/timing_panel.cc
src/wx/video_panel.cc
test/play_test.cc

diff --cc ChangeLog
index 2edfe0e121e482b7af60bd004a583fe869787501,418149a183aef3f12c7979e49399bd3c1be4794b..065a10ae324ca38809de65a83408ab822f3367df
+++ b/ChangeLog
@@@ -1,7 -1,13 +1,17 @@@
 +2014-03-07  Carl Hetherington  <cth@carlh.net>
 +
 +      * Add subtitle view.
 +
+ 2014-03-18  Carl Hetherington  <cth@carlh.net>
+       * Version 1.66.3 released.
+ 2014-03-18  Carl Hetherington  <cth@carlh.net>
+       * Fix bad rounding of timecodes.
+       * Tentative support for 3D from alternate frames of the source.
  2014-03-17  Carl Hetherington  <cth@carlh.net>
  
        * Improve behaviour of the position slider at the end of films.
diff --cc cscript
index b8b0580063ee0490652cd2c8e0b0132360bcf349,7e6b769f075492d66e5ebe2e679f3feb6c2d2640..c07c430310a41ad3f430e1bc60ba8d0123fefe50
+++ b/cscript
@@@ -129,8 -129,8 +129,8 @@@ def make_control(debian_version, bits, 
          print >>f,''
  
  def dependencies(target):
-     return (('ffmpeg-cdist', '08827fa4e1d483511e6135c424d2ca9c56a9ed50'),
+     return (('ffmpeg-cdist', 'a0db025'),
 -            ('libdcp', '8af7b48'))
 +            ('libdcp', '1.0'))
  
  def build(target, options):
      cmd = './waf configure --prefix=%s' % target.work_dir_cscript()
Simple merge
index 90c00283d940fc79c43f1e0cc3131ae92507e01b,b7551c96af36ed3a85e47671ac6e1237a8d96499..86ce7503c9483c192e78c1655c99391f0ba68d36
@@@ -237,7 -239,7 +237,7 @@@ FFmpegContent::information () cons
        
        stringstream s;
        
-       s << String::compose (_("%1 frames; %2 frames per second"), video_length().frames (video_frame_rate()), video_frame_rate()) << "\n";
 -      s << String::compose (_("%1 frames; %2 frames per second"), video_length_after_3d_combine(), video_frame_rate()) << "\n";
++      s << String::compose (_("%1 frames; %2 frames per second"), video_length_after_3d_combine().frames (video_frame_rate()), video_frame_rate()) << "\n";
        s << VideoContent::information ();
  
        return s.str ();
@@@ -265,17 -267,19 +265,15 @@@ FFmpegContent::set_audio_stream (shared
        signal_changed (FFmpegContentProperty::AUDIO_STREAM);
  }
  
 -AudioContent::Frame
 +ContentTime
  FFmpegContent::audio_length () const
  {
-       {
-               boost::mutex::scoped_lock lm (_mutex);
-               if (!_audio_stream) {
-                       return ContentTime ();
-               }
 -      int const cafr = content_audio_frame_rate ();
 -      int const vfr  = video_frame_rate ();
 -      VideoContent::Frame const vl = video_length_after_3d_combine ();
 -
+       boost::mutex::scoped_lock lm (_mutex);
+       if (!_audio_stream) {
 -              return 0;
++              return ContentTime ();
        }
 -      
 -      return video_frames_to_audio_frames (vl, cafr, vfr);
 +
-       return video_length();
++      return video_length ();
  }
  
  int
@@@ -422,7 -427,9 +420,7 @@@ FFmpegContent::full_length () cons
  {
        shared_ptr<const Film> film = _film.lock ();
        assert (film);
-       return DCPTime (video_length(), FrameRateChange (video_frame_rate (), film->video_frame_rate ()));
 -      
 -      FrameRateConversion frc (video_frame_rate (), film->video_frame_rate ());
 -      return video_length_after_3d_combine() * frc.factor() * TIME_HZ / film->video_frame_rate ();
++      return DCPTime (video_length_after_3d_combine(), FrameRateChange (video_frame_rate (), film->video_frame_rate ()));
  }
  
  AudioMapping
Simple merge
Simple merge
index 6a37f30676472c51ec24866179ce5209cc5c2ec8,13f7c52e3d12dec4256479d0d0bdbcec7c795253..d7b37a8353fa5f04b63c58006a2a6c8eade95a1f
@@@ -125,7 -125,9 +125,7 @@@ ImageContent::full_length () cons
  {
        shared_ptr<const Film> film = _film.lock ();
        assert (film);
-       return DCPTime (video_length(), FrameRateChange (video_frame_rate(), film->video_frame_rate()));
 -      
 -      FrameRateConversion frc (video_frame_rate(), film->video_frame_rate ());
 -      return video_length_after_3d_combine() * frc.factor() * TIME_HZ / video_frame_rate();
++      return DCPTime (video_length_after_3d_combine(), FrameRateChange (video_frame_rate(), film->video_frame_rate()));
  }
  
  string
diff --cc src/lib/types.h
Simple merge
diff --cc src/lib/util.cc
Simple merge
index b6a2d031857ad2e9f644ebfa06b5479dcc743989,4a1ef95acfc3335995f420685e3f5d1de0a8fd9e..5864342a265c0fc873c302490acb3191f8f251bd
@@@ -319,24 -319,22 +319,25 @@@ VideoContent::technical_summary () cons
  {
        return String::compose (
                "video: length %1, size %2x%3, rate %4",
-               video_length().seconds(),
 -              video_length_after_3d_combine(), video_size().width, video_size().height, video_frame_rate()
++              video_length_after_3d_combine().seconds(),
 +              video_size().width,
 +              video_size().height,
 +              video_frame_rate()
                );
  }
  
 -libdcp::Size
 +dcp::Size
  VideoContent::video_size_after_3d_split () const
  {
 -      libdcp::Size const s = video_size ();
 +      dcp::Size const s = video_size ();
        switch (video_frame_type ()) {
        case VIDEO_FRAME_TYPE_2D:
+       case VIDEO_FRAME_TYPE_3D_ALTERNATE:
                return s;
        case VIDEO_FRAME_TYPE_3D_LEFT_RIGHT:
 -              return libdcp::Size (s.width / 2, s.height);
 +              return dcp::Size (s.width / 2, s.height);
        case VIDEO_FRAME_TYPE_3D_TOP_BOTTOM:
 -              return libdcp::Size (s.width, s.height / 2);
 +              return dcp::Size (s.width, s.height / 2);
        }
  
        assert (false);
index d2b19480f056f1895ab722d1ee50a96ee1989d37,f846b7ac97a095e4db0eb95d5fb0a33d17f341f2..eeb49cfa543a3ed4a746ae7c01093d7e65eb6f79
@@@ -96,7 -96,16 +96,16 @@@ public
                return _video_length;
        }
  
 -      VideoContent::Frame video_length_after_3d_combine () const {
++      ContentTime video_length_after_3d_combine () const {
+               boost::mutex::scoped_lock lm (_mutex);
+               if (_video_frame_type == VIDEO_FRAME_TYPE_3D_ALTERNATE) {
 -                      return _video_length / 2;
++                      return ContentTime (_video_length.get() / 2);
+               }
+               
+               return _video_length;
+       }
 -      libdcp::Size video_size () const {
 +      dcp::Size video_size () const {
                boost::mutex::scoped_lock lm (_mutex);
                return _video_size;
        }
index 15f91b8923b99ea0a8eff66f3bfc69eb005b4158,3ae963a202f7081322f8e9bab5ab525d0d7309cc..144a494dcd48fc5a6cd9916d4d9a7d40c90fd2e5
@@@ -38,8 -38,11 +38,11 @@@ VideoDecoder::video (shared_ptr<const I
  {
        switch (_video_content->video_frame_type ()) {
        case VIDEO_FRAME_TYPE_2D:
 -              Video (image, EYES_BOTH, same, frame);
 +              _pending.push_back (shared_ptr<DecodedVideo> (new DecodedVideo (time, image, EYES_BOTH, same)));
                break;
 -              Video (image, (frame % 2) ? EYES_RIGHT : EYES_LEFT, same, frame / 2);
+       case VIDEO_FRAME_TYPE_3D_ALTERNATE:
++              Video (image, (frame % 2) ? EYES_RIGHT : EYES_LEFT, same);
+               break;
        case VIDEO_FRAME_TYPE_3D_LEFT_RIGHT:
        {
                int const half = image->size().width / 2;
index 0453272547a65a800eef18b2bc61db41ee1b6654,a8c90b4882623a1ab027bdaee5745769ac6023b5..634a15625c7d1b7ed79f52255f33758f15b4a721
@@@ -83,36 -83,40 +83,40 @@@ Timecode::Timecode (wxWindow* parent
  }
  
  void
 -Timecode::set (Time t, int fps)
 +Timecode::set (DCPTime t, int fps)
  {
-       int const h = t.seconds() / 3600;
-       t -= DCPTime::from_seconds (h * 3600);
-       int const m = t.seconds() / 60;
-       t -= DCPTime::from_seconds (m * 60);
-       int const s = t.seconds();
-       t -= DCPTime::from_seconds (s);
-       int const f = rint (t.seconds() * fps);
+       /* Do this calculation with frames so that we can round
+          to a frame boundary at the start rather than the end.
+       */
 -      int64_t f = divide_with_round (t * fps, TIME_HZ);
++      int64_t f = rint (t.seconds() * fps);
+       
+       int const h = f / (3600 * fps);
+       f -= h * 3600 * fps;
+       int const m = f / (60 * fps);
+       f -= m * 60 * fps;
+       int const s = f / fps;
+       f -= s * fps;
  
        checked_set (_hours, lexical_cast<string> (h));
        checked_set (_minutes, lexical_cast<string> (m));
        checked_set (_seconds, lexical_cast<string> (s));
        checked_set (_frames, lexical_cast<string> (f));
  
-       _fixed->SetLabel (wxString::Format ("%02d:%02d:%02d.%02d", h, m, s, f));
+       _fixed->SetLabel (wxString::Format ("%02d:%02d:%02d.%02ld", h, m, s, f));
  }
  
 -Time
 +DCPTime
  Timecode::get (int fps) const
  {
 -      Time t = 0;
 +      DCPTime t;
        string const h = wx_to_std (_hours->GetValue ());
 -      t += lexical_cast<int> (h.empty() ? "0" : h) * 3600 * TIME_HZ;
 +      t += DCPTime::from_seconds (lexical_cast<int> (h.empty() ? "0" : h) * 3600);
        string const m = wx_to_std (_minutes->GetValue());
 -      t += lexical_cast<int> (m.empty() ? "0" : m) * 60 * TIME_HZ;
 +      t += DCPTime::from_seconds (lexical_cast<int> (m.empty() ? "0" : m) * 60);
        string const s = wx_to_std (_seconds->GetValue());
 -      t += lexical_cast<int> (s.empty() ? "0" : s) * TIME_HZ;
 +      t += DCPTime::from_seconds (lexical_cast<int> (s.empty() ? "0" : s));
        string const f = wx_to_std (_frames->GetValue());
 -      t += lexical_cast<int> (f.empty() ? "0" : f) * TIME_HZ / fps;
 +      t += DCPTime::from_seconds (lexical_cast<double> (f.empty() ? "0" : f) / fps);
  
        return t;
  }
index b8b923a6b941752c80962fc6088430d4b715a12f,2321fd0dfdbfb7ac84ce8f1d12b603d9064adcf9..3fcb9b1753eeecc41d808ef2d27f7777196d1bbe
@@@ -85,9 -85,13 +85,13 @@@ TimingPanel::film_content_changed (int 
                if (content) {
                        _position->set (content->position (), _editor->film()->video_frame_rate ());
                } else {
 -                      _position->set (0, 24);
 +                      _position->set (DCPTime () , 24);
                }
-       } else if (property == ContentProperty::LENGTH || property == VideoContentProperty::VIDEO_FRAME_RATE) {
+       } else if (
+               property == ContentProperty::LENGTH ||
+               property == VideoContentProperty::VIDEO_FRAME_RATE ||
+               property == VideoContentProperty::VIDEO_FRAME_TYPE
+               ) {
                if (content) {
                        _full_length->set (content->full_length (), _editor->film()->video_frame_rate ());
                        _play_length->set (content->length_after_trim (), _editor->film()->video_frame_rate ());
Simple merge
index 690b042d8c32722f78e1c75e5c800e22cc685251,51e2272568acbf26a1bc321d0ad1bdf63af3bc36..ed3e497ed6e3c4fc6248537ad1e98f7d22ce1241
@@@ -89,13 -89,13 +89,13 @@@ BOOST_AUTO_TEST_CASE (play_test
        film->examine_and_add_content (A);
        wait_for_jobs ();
  
-       BOOST_CHECK_EQUAL (A->video_length().frames (24), 16);
 -      BOOST_CHECK_EQUAL (A->video_length_after_3d_combine(), 16);
++      BOOST_CHECK_EQUAL (A->video_length_after_3d_combine().frames (24), 16);
  
        shared_ptr<FFmpegContent> B (new FFmpegContent (film, "test/data/red_30.mp4"));
        film->examine_and_add_content (B);
        wait_for_jobs ();
  
-       BOOST_CHECK_EQUAL (B->video_length().frames (30), 16);
 -      BOOST_CHECK_EQUAL (B->video_length_after_3d_combine(), 16);
++      BOOST_CHECK_EQUAL (B->video_length_after_3d_combine().frames (30), 16);
        
        /* Film should have been set to 25fps */
        BOOST_CHECK_EQUAL (film->video_frame_rate(), 25);