+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.
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()
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 ();
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
{
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
{
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
{
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);
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;
}
{
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;
}
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;
}
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 ());
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);