/*
- Copyright (C) 2013-2015 Carl Hetherington <cth@carlh.net>
+ Copyright (C) 2013-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
#include "raw_convert.h"
#include "compose.hpp"
#include <libcxml/cxml.h>
+#include <libxml++/libxml++.h>
#include <boost/foreach.hpp>
+#include <iostream>
#include "i18n.h"
using std::vector;
using std::stringstream;
using std::fixed;
+using std::list;
+using std::pair;
using std::setprecision;
using boost::shared_ptr;
using boost::dynamic_pointer_cast;
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)
AudioContent::AudioContent (shared_ptr<const Film> film, cxml::ConstNodePtr node)
: Content (film, node)
{
- _audio_gain = node->number_child<float> ("AudioGain");
+ _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)
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
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()));
+ }
}
}
AudioMapping merged (channels, MAX_DCP_AUDIO_CHANNELS);
+ merged.make_zero ();
int c = 0;
int s = 0;
AudioMapping mapping = i->mapping ();
for (int j = 0; j < mapping.input_channels(); ++j) {
for (int k = 0; k < MAX_DCP_AUDIO_CHANNELS; ++k) {
- merged.set (c, k, mapping.get (j, k));
+ if (k < mapping.output_channels()) {
+ merged.set (c, k, mapping.get (j, k));
+ }
}
++c;
}
int
AudioContent::resampled_audio_frame_rate () const
{
- shared_ptr<const Film> film = _film.lock ();
- DCPOMATIC_ASSERT (film);
-
/* 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
return n;
}
+
+void
+AudioContent::add_properties (list<UserProperty>& p) const
+{
+ shared_ptr<const AudioStream> stream;
+ if (audio_streams().size() == 1) {
+ stream = audio_streams().front ();
+ }
+
+ if (stream) {
+ p.push_back (UserProperty (_("Audio"), _("Channels"), stream->channels ()));
+ p.push_back (UserProperty (_("Audio"), _("Content audio frame rate"), stream->frame_rate(), _("Hz")));
+ }
+
+ FrameRateChange const frc (audio_video_frame_rate(), film()->video_frame_rate());
+ ContentTime const c (full_length(), frc);
+
+ p.push_back (
+ UserProperty (_("Length"), _("Full length in video frames at content rate"), c.frames_round(frc.source))
+ );
+
+ if (stream) {
+ p.push_back (
+ UserProperty (
+ _("Length"),
+ _("Full length in audio frames at content rate"),
+ c.frames_round (stream->frame_rate ())
+ )
+ );
+ }
+
+ p.push_back (UserProperty (_("Audio"), _("DCP frame rate"), resampled_audio_frame_rate (), _("Hz")));
+ p.push_back (UserProperty (_("Length"), _("Full length in video frames at DCP rate"), c.frames_round (frc.dcp)));
+
+ if (stream) {
+ p.push_back (
+ UserProperty (
+ _("Length"),
+ _("Full length in audio frames at DCP rate"),
+ c.frames_round (resampled_audio_frame_rate ())
+ )
+ );
+ }
+}
+
+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;
+}