Allow setup of the frame rate that audio content is prepared for.
authorCarl Hetherington <cth@carlh.net>
Fri, 15 Apr 2016 18:49:09 +0000 (19:49 +0100)
committerCarl Hetherington <cth@carlh.net>
Fri, 15 Apr 2016 18:49:09 +0000 (19:49 +0100)
ChangeLog
src/lib/audio_content.cc
src/lib/audio_content.h
src/lib/sndfile_content.cc
src/wx/audio_panel.cc
src/wx/timing_panel.cc

index 5fb120ac58f941c162f7c12b4cac8ac8ca4c3e59..2028d75aae90f0fec443b801fb3771b4844318ef 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,7 @@
 2016-04-15  Carl Hetherington  <cth@carlh.net>
 
+       * Fix forcing of the "video frame rate" for audio content.
+
        * Updated ru_RU and uk_UA translations from Igor Voytovich.
 
 2016-04-14  Carl Hetherington  <cth@carlh.net>
index ee5bb69a2831cca2479c4034661b32a68012d54a..bd4bb565ff73c9b8e553369a9a40d5f7d3968365 100644 (file)
@@ -47,6 +47,7 @@ using boost::optional;
 int const AudioContentProperty::AUDIO_STREAMS = 200;
 int const AudioContentProperty::AUDIO_GAIN = 201;
 int const AudioContentProperty::AUDIO_DELAY = 202;
+int const AudioContentProperty::AUDIO_VIDEO_FRAME_RATE = 203;
 
 AudioContent::AudioContent (shared_ptr<const Film> film)
        : Content (film)
@@ -77,6 +78,7 @@ AudioContent::AudioContent (shared_ptr<const Film> film, cxml::ConstNodePtr node
 {
        _audio_gain = node->number_child<double> ("AudioGain");
        _audio_delay = node->number_child<int> ("AudioDelay");
+       _audio_video_frame_rate = node->optional_number_child<double> ("AudioVideoFrameRate");
 }
 
 AudioContent::AudioContent (shared_ptr<const Film> film, vector<shared_ptr<Content> > c)
@@ -95,10 +97,16 @@ AudioContent::AudioContent (shared_ptr<const Film> film, vector<shared_ptr<Conte
                if (ac->audio_delay() != ref->audio_delay()) {
                        throw JoinError (_("Content to be joined must have the same audio delay."));
                }
+
+               if (ac->audio_video_frame_rate() != ref->audio_video_frame_rate()) {
+                       throw JoinError (_("Content to be joined must have the same video frame rate."));
+               }
        }
 
        _audio_gain = ref->audio_gain ();
        _audio_delay = ref->audio_delay ();
+       /* Preserve the optional<> part of this */
+       _audio_video_frame_rate = ref->_audio_video_frame_rate;
 }
 
 void
@@ -107,6 +115,9 @@ AudioContent::as_xml (xmlpp::Node* node) const
        boost::mutex::scoped_lock lm (_mutex);
        node->add_child("AudioGain")->add_child_text (raw_convert<string> (_audio_gain));
        node->add_child("AudioDelay")->add_child_text (raw_convert<string> (_audio_delay));
+       if (_audio_video_frame_rate) {
+               node->add_child("AudioVideoFrameRate")->add_child_text (raw_convert<string> (_audio_video_frame_rate.get()));
+       }
 }
 
 
@@ -199,7 +210,7 @@ AudioContent::resampled_audio_frame_rate () const
        /* Resample to a DCI-approved sample rate */
        double t = has_rate_above_48k() ? 96000 : 48000;
 
-       FrameRateChange frc = film()->active_frame_rate_change (position ());
+       FrameRateChange frc (audio_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
@@ -308,10 +319,7 @@ AudioContent::add_properties (list<UserProperty>& p) const
                p.push_back (UserProperty (_("Audio"), _("Content audio frame rate"), stream->frame_rate(), _("Hz")));
        }
 
-       shared_ptr<const Film> film = _film.lock ();
-       DCPOMATIC_ASSERT (film);
-
-       FrameRateChange const frc = film->active_frame_rate_change (position ());
+       FrameRateChange const frc (audio_video_frame_rate(), film()->video_frame_rate());
        ContentTime const c (full_length(), frc);
 
        p.push_back (
@@ -341,3 +349,30 @@ AudioContent::add_properties (list<UserProperty>& p) const
                        );
        }
 }
+
+void
+AudioContent::set_audio_video_frame_rate (double r)
+{
+       {
+               boost::mutex::scoped_lock lm (_mutex);
+               _audio_video_frame_rate = r;
+       }
+
+       signal_changed (AudioContentProperty::AUDIO_VIDEO_FRAME_RATE);
+}
+
+double
+AudioContent::audio_video_frame_rate () const
+{
+       {
+               boost::mutex::scoped_lock lm (_mutex);
+               if (_audio_video_frame_rate) {
+                       return _audio_video_frame_rate.get ();
+               }
+       }
+
+       /* No frame rate specified, so assume this content has been
+          prepared for any concurrent video content.
+       */
+       return film()->active_frame_rate_change(position()).source;
+}
index 33c52aa73688d54b042c97adce84b96da4f074f9..ac91da595655dcb49382904182656c78d3f8e193 100644 (file)
@@ -37,6 +37,7 @@ public:
        static int const AUDIO_STREAMS;
        static int const AUDIO_GAIN;
        static int const AUDIO_DELAY;
+       static int const AUDIO_VIDEO_FRAME_RATE;
 };
 
 /** @class AudioContent
@@ -75,6 +76,9 @@ public:
                return _audio_delay;
        }
 
+       double audio_video_frame_rate () const;
+       void set_audio_video_frame_rate (double r);
+
        std::string processing_description () const;
 
 protected:
@@ -86,6 +90,7 @@ private:
        double _audio_gain;
        /** Delay to apply to audio (positive moves audio later) in milliseconds */
        int _audio_delay;
+       boost::optional<double> _audio_video_frame_rate;
 };
 
 #endif
index c4f418775f7d4126c1a824a2e13b35d08d2f25df..f9eb62a2bb790a6e1e2c5841db82f751e8a36814 100644 (file)
@@ -106,6 +106,6 @@ SndfileContent::take_from_audio_examiner (shared_ptr<AudioExaminer> examiner)
 DCPTime
 SndfileContent::full_length () const
 {
-       FrameRateChange const frc = film()->active_frame_rate_change (position ());
+       FrameRateChange const frc (audio_video_frame_rate(), film()->video_frame_rate());
        return DCPTime::from_frames (audio_length() / frc.speed_up, audio_stream()->frame_rate ());
 }
index 10f855cfed682cb4185a4bdc85d6a0ba2b5ddd72..9e2ba986939dea29fd6b9aebd00735eea15bf000 100644 (file)
@@ -167,6 +167,8 @@ AudioPanel::film_content_changed (int property)
                }
 
                setup_sensitivity ();
+       } else if (property == AudioContentProperty::AUDIO_VIDEO_FRAME_RATE) {
+               setup_description ();
        }
 }
 
index a29240f8dbaf3cd2eea395c133dc885ff0cc918b..c8fd9984fe3008445b2b4a8e429fd11495c67001 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 program is free software; you can redistribute it and/or modify
     it under the terms of the GNU General Public License as published by
@@ -27,6 +27,7 @@
 #include "lib/raw_convert.h"
 #include "lib/subtitle_content.h"
 #include "lib/dcp_subtitle_content.h"
+#include "lib/audio_content.h"
 #include "lib/text_subtitle_content.h"
 #include <boost/foreach.hpp>
 #include <set>
@@ -209,6 +210,7 @@ TimingPanel::film_content_changed (int property)
                property == ContentProperty::LENGTH ||
                property == VideoContentProperty::VIDEO_FRAME_RATE ||
                property == VideoContentProperty::VIDEO_FRAME_TYPE ||
+               property == AudioContentProperty::AUDIO_VIDEO_FRAME_RATE ||
                property == SubtitleContentProperty::SUBTITLE_VIDEO_FRAME_RATE
                ) {
 
@@ -247,6 +249,7 @@ TimingPanel::film_content_changed (int property)
                property == ContentProperty::TRIM_END ||
                property == VideoContentProperty::VIDEO_FRAME_RATE ||
                property == VideoContentProperty::VIDEO_FRAME_TYPE ||
+               property == AudioContentProperty::AUDIO_VIDEO_FRAME_RATE ||
                property == SubtitleContentProperty::SUBTITLE_VIDEO_FRAME_RATE
                ) {
 
@@ -256,6 +259,8 @@ TimingPanel::film_content_changed (int property)
        if (property == VideoContentProperty::VIDEO_FRAME_RATE || property == SubtitleContentProperty::SUBTITLE_VIDEO_FRAME_RATE) {
                set<double> check_vc;
                shared_ptr<const VideoContent> vc;
+               int count_ac = 0;
+               shared_ptr<const AudioContent> ac;
                int count_sc = 0;
                shared_ptr<const SubtitleContent> sc;
                BOOST_FOREACH (shared_ptr<const Content> i, _parent->selected ()) {
@@ -264,6 +269,11 @@ TimingPanel::film_content_changed (int property)
                                check_vc.insert (vt->video_frame_rate ());
                                vc = vt;
                        }
+                       shared_ptr<const AudioContent> at = dynamic_pointer_cast<const AudioContent> (i);
+                       if (at) {
+                               ++count_ac;
+                               ac = at;
+                       }
                        shared_ptr<const SubtitleContent> st = dynamic_pointer_cast<const SubtitleContent> (i);
                        if (st) {
                                ++count_sc;
@@ -274,9 +284,11 @@ TimingPanel::film_content_changed (int property)
 
                bool const single_frame_image_content = vc && dynamic_pointer_cast<const ImageContent> (vc) && vc->number_of_paths() == 1;
 
-               if ((check_vc.size() == 1 || count_sc == 1) && !single_frame_image_content) {
+               if ((check_vc.size() == 1 || count_ac == 1 || count_sc == 1) && !single_frame_image_content) {
                        if (vc) {
                                checked_set (_video_frame_rate, raw_convert<string> (vc->video_frame_rate (), 5));
+                       } else if (ac) {
+                               checked_set (_video_frame_rate, raw_convert<string> (ac->audio_video_frame_rate (), 5));
                        } else if (sc) {
                                checked_set (_video_frame_rate, raw_convert<string> (sc->subtitle_video_frame_rate (), 5));
                        }
@@ -392,14 +404,19 @@ TimingPanel::set_video_frame_rate ()
 {
        BOOST_FOREACH (shared_ptr<Content> i, _parent->selected ()) {
                shared_ptr<VideoContent> vc = dynamic_pointer_cast<VideoContent> (i);
+               shared_ptr<AudioContent> ac = dynamic_pointer_cast<AudioContent> (i);
                shared_ptr<DCPSubtitleContent> dsc = dynamic_pointer_cast<DCPSubtitleContent> (i);
                shared_ptr<TextSubtitleContent> tsc = dynamic_pointer_cast<TextSubtitleContent> (i);
+               double const fr = raw_convert<double> (wx_to_std (_video_frame_rate->GetValue ()));
                if (vc) {
-                       vc->set_video_frame_rate (raw_convert<double> (wx_to_std (_video_frame_rate->GetValue ())));
+                       vc->set_video_frame_rate (fr);
+               } else if (ac) {
+                       /* Audio but not video, i.e. SndfileContent */
+                       ac->set_audio_video_frame_rate (fr);
                } else if (dsc) {
-                       dsc->set_subtitle_video_frame_rate (raw_convert<double> (wx_to_std (_video_frame_rate->GetValue ())));
+                       dsc->set_subtitle_video_frame_rate (fr);
                } else if (tsc) {
-                       tsc->set_subtitle_video_frame_rate (raw_convert<double> (wx_to_std (_video_frame_rate->GetValue ())));
+                       tsc->set_subtitle_video_frame_rate (fr);
                }
                _set_video_frame_rate->Enable (false);
        }
@@ -416,6 +433,7 @@ TimingPanel::content_selection_changed ()
        film_content_changed (ContentProperty::TRIM_END);
        film_content_changed (VideoContentProperty::VIDEO_FRAME_RATE);
        film_content_changed (SubtitleContentProperty::SUBTITLE_VIDEO_FRAME_RATE);
+       film_content_changed (AudioContentProperty::AUDIO_VIDEO_FRAME_RATE);
 }
 
 void