summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorCarl Hetherington <cth@carlh.net>2013-07-08 23:23:07 +0100
committerCarl Hetherington <cth@carlh.net>2013-07-08 23:23:07 +0100
commitf1fab174c7db85a1641bca2830ea75829982723f (patch)
tree80f64c7f5daf22f129b5e286487a704c6c069e14 /src
parent2b4110534a7e3b2a2905c9f25226ba5c1ba4a167 (diff)
parent50e6acde52c7eaa3afa239bc14f08eced3787bd9 (diff)
Merge branch 'staging'
Diffstat (limited to 'src')
-rw-r--r--src/lib/combiner.cc8
-rw-r--r--src/lib/encoder.cc19
-rw-r--r--src/lib/film.cc15
-rw-r--r--src/lib/film.h10
-rw-r--r--src/lib/transcoder.cc2
-rw-r--r--src/lib/util.cc20
-rw-r--r--src/lib/util.h6
-rw-r--r--src/lib/writer.cc2
-rw-r--r--src/tools/dvdomatic.cc2
-rw-r--r--src/wx/audio_dialog.cc6
-rw-r--r--src/wx/film_editor.cc55
-rw-r--r--src/wx/film_editor.h5
12 files changed, 137 insertions, 13 deletions
diff --git a/src/lib/combiner.cc b/src/lib/combiner.cc
index 367cefa7f..f7d634832 100644
--- a/src/lib/combiner.cc
+++ b/src/lib/combiner.cc
@@ -45,6 +45,14 @@ Combiner::process_video (shared_ptr<const Image> image, bool, shared_ptr<Subtitl
void
Combiner::process_video_b (shared_ptr<const Image> image, bool, shared_ptr<Subtitle> sub, double t)
{
+ if (!_image) {
+ /* It's possible for filters in the A-side to mean that we get a B frame
+ before any A; just skip the B frame in that case. This at least prevents
+ a crash, but may not be right.
+ */
+ return;
+ }
+
/* Copy the right half of this image into our _image */
/* XXX: this should probably be in the Image class */
for (int i = 0; i < image->components(); ++i) {
diff --git a/src/lib/encoder.cc b/src/lib/encoder.cc
index 2c989452d..0ac32d3bf 100644
--- a/src/lib/encoder.cc
+++ b/src/lib/encoder.cc
@@ -47,6 +47,7 @@ using std::stringstream;
using std::vector;
using std::list;
using std::cout;
+using std::min;
using std::make_pair;
using namespace boost;
@@ -149,6 +150,20 @@ Encoder::process_end ()
}
#endif
+ if (_film->audio_channels() == 0 && _film->minimum_audio_channels() > 0) {
+ /* Put audio in where there is none at all */
+ int64_t af = video_frames_to_audio_frames (_video_frames_out, 48000, _film->dcp_frame_rate ());
+ while (af) {
+ int64_t const this_time = min (af, static_cast<int64_t> (24000));
+ shared_ptr<AudioBuffers> out (new AudioBuffers (_film->minimum_audio_channels(), this_time));
+ out->make_silent ();
+ out->set_frames (this_time);
+ write_audio (out);
+
+ af -= this_time;
+ }
+ }
+
boost::mutex::scoped_lock lock (_mutex);
_film->log()->log (String::compose (N_("Clearing queue of %1"), _queue.size ()));
@@ -433,10 +448,10 @@ Encoder::encoder_thread (ServerDescription* server)
void
Encoder::write_audio (shared_ptr<const AudioBuffers> data)
{
- AudioMapping m (_film->audio_channels ());
+ AudioMapping m (_film);
if (m.dcp_channels() != _film->audio_channels()) {
- /* Remap (currently just for mono -> 5.1) */
+ /* Remap and pad with silence */
shared_ptr<AudioBuffers> b (new AudioBuffers (m.dcp_channels(), data->frames ()));
for (int i = 0; i < m.dcp_channels(); ++i) {
diff --git a/src/lib/film.cc b/src/lib/film.cc
index d92d7a977..ce555ac8b 100644
--- a/src/lib/film.cc
+++ b/src/lib/film.cc
@@ -108,6 +108,7 @@ Film::Film (string d, bool must_exist)
, _j2k_bandwidth (200000000)
, _dci_metadata (Config::instance()->default_dci_metadata ())
, _dcp_frame_rate (0)
+ , _minimum_audio_channels (0)
, _source_frame_rate (0)
, _dirty (false)
{
@@ -185,6 +186,7 @@ Film::Film (Film const & o)
, _dci_metadata (o._dci_metadata)
, _dci_date (o._dci_date)
, _dcp_frame_rate (o._dcp_frame_rate)
+ , _minimum_audio_channels (o._minimum_audio_channels)
, _size (o._size)
, _length (o._length)
, _content_digest (o._content_digest)
@@ -506,6 +508,7 @@ Film::write_metadata () const
_dci_metadata.write (f);
f << "dci_date " << boost::gregorian::to_iso_string (_dci_date) << endl;
f << "dcp_frame_rate " << _dcp_frame_rate << endl;
+ f << "minimum_audio_channels " << _minimum_audio_channels << endl;
f << "width " << _size.width << endl;
f << "height " << _size.height << endl;
f << "length " << _length.get_value_or(0) << endl;
@@ -642,6 +645,8 @@ Film::read_metadata ()
_dci_date = boost::gregorian::from_undelimited_string (v);
} else if (k == "dcp_frame_rate") {
_dcp_frame_rate = atoi (v.c_str ());
+ } else if (k == "minimum_audio_channels") {
+ _minimum_audio_channels = atoi (v.c_str ());
}
_dci_metadata.read (k, v);
@@ -1324,6 +1329,16 @@ Film::set_dcp_frame_rate (int f)
}
void
+Film::set_minimum_audio_channels (int c)
+{
+ {
+ boost::mutex::scoped_lock lm (_state_mutex);
+ _minimum_audio_channels = c;
+ }
+ signal_changed (MINIMUM_AUDIO_CHANNELS);
+}
+
+void
Film::set_size (libdcp::Size s)
{
{
diff --git a/src/lib/film.h b/src/lib/film.h
index dd0a83d94..ca9bd57f4 100644
--- a/src/lib/film.h
+++ b/src/lib/film.h
@@ -153,7 +153,8 @@ public:
CONTENT_AUDIO_STREAMS,
SUBTITLE_STREAMS,
SOURCE_FRAME_RATE,
- DCP_FRAME_RATE
+ DCP_FRAME_RATE,
+ MINIMUM_AUDIO_CHANNELS
};
@@ -335,6 +336,11 @@ public:
return _source_frame_rate;
}
+ int minimum_audio_channels () const {
+ boost::mutex::scoped_lock lm (_state_mutex);
+ return _minimum_audio_channels;
+ }
+
boost::shared_ptr<AudioStream> audio_stream () const;
bool has_audio () const;
@@ -379,6 +385,7 @@ public:
void set_content_audio_streams (std::vector<boost::shared_ptr<AudioStream> >);
void set_subtitle_streams (std::vector<boost::shared_ptr<SubtitleStream> >);
void set_source_frame_rate (float);
+ void set_minimum_audio_channels (int);
/** Emitted when some property has changed */
mutable boost::signals2::signal<void (Property)> Changed;
@@ -481,6 +488,7 @@ private:
boost::gregorian::date _dci_date;
/** Frames per second to run our DCP at */
int _dcp_frame_rate;
+ int _minimum_audio_channels;
/* Data which are cached to speed things up */
diff --git a/src/lib/transcoder.cc b/src/lib/transcoder.cc
index 48cf402d7..a202d440c 100644
--- a/src/lib/transcoder.cc
+++ b/src/lib/transcoder.cc
@@ -73,7 +73,7 @@ Transcoder::Transcoder (shared_ptr<Film> f, DecodeOptions o, Job* j, shared_ptr<
/* Set up the decoder to use the film's set streams */
_decoders.video->set_subtitle_stream (f->subtitle_stream ());
if (f->audio_stream ()) {
- _decoders.audio->set_audio_stream (f->audio_stream ());
+ _decoders.audio->set_audio_stream (f->audio_stream ());
}
_decoders.video->connect_video (_delay_line);
diff --git a/src/lib/util.cc b/src/lib/util.cc
index 4cf57368a..83980f828 100644
--- a/src/lib/util.cc
+++ b/src/lib/util.cc
@@ -61,6 +61,7 @@ extern "C" {
#include "filter.h"
#include "sound_processor.h"
#include "config.h"
+#include "film.h"
#ifdef DVDOMATIC_WINDOWS
#include "stack.hpp"
#endif
@@ -962,8 +963,9 @@ audio_channel_name (int c)
return channels[c];
}
-AudioMapping::AudioMapping (int c)
- : _source_channels (c)
+AudioMapping::AudioMapping (shared_ptr<const Film> f)
+ : _source_channels (f->audio_stream() ? f->audio_stream()->channels() : 0)
+ , _minimum_channels (f->minimum_audio_channels ())
{
}
@@ -1001,8 +1003,11 @@ AudioMapping::dcp_to_source (libdcp::Channel c) const
return static_cast<int> (c);
}
+/** @return minimum number of DCP channels that we can allow in this
+ DCP, given the nature of the source.
+*/
int
-AudioMapping::dcp_channels () const
+AudioMapping::minimum_dcp_channels () const
{
if (_source_channels == 1) {
/* The source is mono, so to put the mono channel into
@@ -1014,6 +1019,15 @@ AudioMapping::dcp_channels () const
return _source_channels;
}
+/** @return number of channels that there should be in the DCP, including
+ * any silent padded ones.
+ */
+int
+AudioMapping::dcp_channels () const
+{
+ return max (_source_channels, _minimum_channels);
+}
+
FrameRateConversion::FrameRateConversion (float source, int dcp)
: skip (false)
, repeat (false)
diff --git a/src/lib/util.h b/src/lib/util.h
index 0d745e50c..c9e5bef16 100644
--- a/src/lib/util.h
+++ b/src/lib/util.h
@@ -50,6 +50,7 @@ extern "C" {
#define MAX_AUDIO_CHANNELS 6
class Scaler;
+class Film;
extern std::string seconds_to_hms (int);
extern std::string seconds_to_approximate_hms (int);
@@ -287,14 +288,17 @@ private:
class AudioMapping
{
public:
- AudioMapping (int);
+ AudioMapping (boost::shared_ptr<const Film>);
boost::optional<libdcp::Channel> source_to_dcp (int c) const;
boost::optional<int> dcp_to_source (libdcp::Channel c) const;
+
+ int minimum_dcp_channels () const;
int dcp_channels () const;
private:
int _source_channels;
+ int _minimum_channels;
};
extern int64_t video_frames_to_audio_frames (SourceFrame v, float audio_sample_rate, float frames_per_second);
diff --git a/src/lib/writer.cc b/src/lib/writer.cc
index 1a6daa1db..cff0b5be2 100644
--- a/src/lib/writer.cc
+++ b/src/lib/writer.cc
@@ -77,7 +77,7 @@ Writer::Writer (shared_ptr<Film> f)
_picture_asset_writer = _picture_asset->start_write (_first_nonexistant_frame > 0);
- AudioMapping m (_film->audio_channels ());
+ AudioMapping m (_film);
if (m.dcp_channels() > 0) {
_sound_asset.reset (
diff --git a/src/tools/dvdomatic.cc b/src/tools/dvdomatic.cc
index de94d0a2f..e0629bb98 100644
--- a/src/tools/dvdomatic.cc
+++ b/src/tools/dvdomatic.cc
@@ -166,7 +166,7 @@ setup_menu (wxMenuBar* m)
add_item (file, _("&Properties..."), ID_file_properties, NEEDS_FILM);
#ifndef __WXOSX__
file->AppendSeparator ();
-#endif
+#endif
add_item (file, _("&Exit"), wxID_EXIT, ALWAYS);
#ifdef __WXOSX__
diff --git a/src/wx/audio_dialog.cc b/src/wx/audio_dialog.cc
index d12b5516f..21e4e5940 100644
--- a/src/wx/audio_dialog.cc
+++ b/src/wx/audio_dialog.cc
@@ -108,7 +108,7 @@ AudioDialog::setup_channels ()
return;
}
- AudioMapping m (_film->audio_stream()->channels ());
+ AudioMapping m (_film);
for (int i = 0; i < MAX_AUDIO_CHANNELS; ++i) {
if (m.dcp_to_source(static_cast<libdcp::Channel>(i))) {
@@ -134,7 +134,7 @@ AudioDialog::try_to_load_analysis ()
_plot->set_analysis (a);
- AudioMapping m (_film->audio_stream()->channels ());
+ AudioMapping m (_film);
optional<libdcp::Channel> c = m.source_to_dcp (0);
if (c) {
_channel_checkbox[c.get()]->SetValue (true);
@@ -157,7 +157,7 @@ AudioDialog::channel_clicked (wxCommandEvent& ev)
assert (c < MAX_AUDIO_CHANNELS);
- AudioMapping m (_film->audio_stream()->channels ());
+ AudioMapping m (_film);
optional<int> s = m.dcp_to_source (static_cast<libdcp::Channel> (c));
if (s) {
_plot->set_channel_visible (s.get(), _channel_checkbox[c]->GetValue ());
diff --git a/src/wx/film_editor.cc b/src/wx/film_editor.cc
index d81bce9b2..b9ad12d64 100644
--- a/src/wx/film_editor.cc
+++ b/src/wx/film_editor.cc
@@ -237,6 +237,8 @@ FilmEditor::connect_to_widgets ()
_dcp_content_type->Connect (wxID_ANY, wxEVT_COMMAND_CHOICE_SELECTED, wxCommandEventHandler (FilmEditor::dcp_content_type_changed), 0, this);
_dcp_frame_rate->Connect (wxID_ANY, wxEVT_COMMAND_CHOICE_SELECTED, wxCommandEventHandler (FilmEditor::dcp_frame_rate_changed), 0, this);
_best_dcp_frame_rate->Connect (wxID_ANY, wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler (FilmEditor::best_dcp_frame_rate_clicked), 0, this);
+ _pad_with_silence->Connect (wxID_ANY, wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler (FilmEditor::pad_with_silence_toggled), 0, this);
+ _minimum_audio_channels->Connect (wxID_ANY, wxEVT_COMMAND_SPINCTRL_UPDATED, wxCommandEventHandler (FilmEditor::minimum_audio_channels_changed), 0, this);
_dcp_ab->Connect (wxID_ANY, wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler (FilmEditor::dcp_ab_toggled), 0, this);
_still_duration->Connect (wxID_ANY, wxEVT_COMMAND_SPINCTRL_UPDATED, wxCommandEventHandler (FilmEditor::still_duration_changed), 0, this);
_trim_start->Connect (wxID_ANY, wxEVT_COMMAND_SPINCTRL_UPDATED, wxCommandEventHandler (FilmEditor::trim_start_changed), 0, this);
@@ -398,6 +400,16 @@ FilmEditor::make_audio_panel ()
}
{
+ _pad_with_silence = new wxCheckBox (_audio_panel, wxID_ANY, _("Pad with silence to"));
+ grid->Add (_pad_with_silence);
+ wxBoxSizer* s = new wxBoxSizer (wxHORIZONTAL);
+ _minimum_audio_channels = new wxSpinCtrl (_audio_panel);
+ s->Add (_minimum_audio_channels, 1);
+ add_label_to_sizer (s, _audio_panel, _("channels"));
+ grid->Add (s);
+ }
+
+ {
_use_content_audio = new wxRadioButton (_audio_panel, wxID_ANY, _("Use content's audio"), wxDefaultPosition, wxDefaultSize, wxRB_GROUP);
grid->Add (video_control (_use_content_audio));
wxBoxSizer* s = new wxBoxSizer (wxHORIZONTAL);
@@ -420,6 +432,7 @@ FilmEditor::make_audio_panel ()
_audio_gain->SetRange (-60, 60);
_audio_delay->SetRange (-1000, 1000);
+ _minimum_audio_channels->SetRange (0, MAX_AUDIO_CHANNELS);
}
void
@@ -633,6 +646,7 @@ FilmEditor::film_changed (Film::Property p)
setup_streams ();
setup_show_audio_sensitivity ();
setup_frame_rate_description ();
+ setup_minimum_audio_channels ();
break;
case Film::TRUST_CONTENT_HEADER:
checked_set (_trust_content_header, _film->trust_content_header ());
@@ -645,6 +659,7 @@ FilmEditor::film_changed (Film::Property p)
setup_streams ();
setup_show_audio_sensitivity ();
setup_frame_rate_description ();
+ setup_minimum_audio_channels ();
break;
case Film::FORMAT:
{
@@ -769,6 +784,7 @@ FilmEditor::film_changed (Film::Property p)
setup_audio_control_sensitivity ();
setup_show_audio_sensitivity ();
setup_frame_rate_description ();
+ setup_minimum_audio_channels ();
break;
case Film::USE_CONTENT_AUDIO:
_film->log()->log (String::compose ("Film::USE_CONTENT_AUDIO changed; setting GUI using %1", _film->use_content_audio ()));
@@ -779,6 +795,7 @@ FilmEditor::film_changed (Film::Property p)
setup_audio_control_sensitivity ();
setup_show_audio_sensitivity ();
setup_frame_rate_description ();
+ setup_minimum_audio_channels ();
break;
case Film::SUBTITLE_STREAM:
if (_film->subtitle_stream()) {
@@ -794,6 +811,7 @@ FilmEditor::film_changed (Film::Property p)
setup_audio_details ();
setup_show_audio_sensitivity ();
setup_frame_rate_description ();
+ setup_minimum_audio_channels ();
break;
}
case Film::DCP_FRAME_RATE:
@@ -813,6 +831,10 @@ FilmEditor::film_changed (Film::Property p)
}
setup_frame_rate_description ();
+ case Film::MINIMUM_AUDIO_CHANNELS:
+ checked_set (_minimum_audio_channels, _film->minimum_audio_channels ());
+ setup_minimum_audio_channels ();
+ break;
}
}
@@ -1190,6 +1212,9 @@ FilmEditor::setup_audio_control_sensitivity ()
for (int i = 0; i < MAX_AUDIO_CHANNELS; ++i) {
_external_audio[i]->Enable (external);
}
+
+ _pad_with_silence->Enable (_generally_sensitive && _film && _film->audio_stream() && _film->audio_stream()->channels() < MAX_AUDIO_CHANNELS);
+ _minimum_audio_channels->Enable (_generally_sensitive && _pad_with_silence->GetValue ());
}
void
@@ -1416,3 +1441,33 @@ FilmEditor::trim_type_changed (wxCommandEvent &)
{
_film->set_trim_type (_trim_type->GetSelection () == 0 ? Film::CPL : Film::ENCODE);
}
+
+void
+FilmEditor::setup_minimum_audio_channels ()
+{
+ if (!_film || !_film->audio_stream ()) {
+ _pad_with_silence->SetValue (false);
+ return;
+ }
+
+ _pad_with_silence->SetValue (_film->audio_stream()->channels() < _film->minimum_audio_channels());
+
+ AudioMapping m (_film);
+ _minimum_audio_channels->SetRange (m.minimum_dcp_channels() + 1, MAX_AUDIO_CHANNELS);
+}
+
+void
+FilmEditor::pad_with_silence_toggled (wxCommandEvent &)
+{
+ setup_audio_control_sensitivity ();
+}
+
+void
+FilmEditor::minimum_audio_channels_changed (wxCommandEvent &)
+{
+ if (!_film) {
+ return;
+ }
+
+ _film->set_minimum_audio_channels (_minimum_audio_channels->GetValue ());
+}
diff --git a/src/wx/film_editor.h b/src/wx/film_editor.h
index e2a4d5836..c2d064ca2 100644
--- a/src/wx/film_editor.h
+++ b/src/wx/film_editor.h
@@ -85,6 +85,8 @@ private:
void external_audio_changed (wxCommandEvent &);
void dcp_frame_rate_changed (wxCommandEvent &);
void best_dcp_frame_rate_clicked (wxCommandEvent &);
+ void pad_with_silence_toggled (wxCommandEvent &);
+ void minimum_audio_channels_changed (wxCommandEvent &);
/* Handle changes to the model */
void film_changed (Film::Property);
@@ -103,6 +105,7 @@ private:
void setup_scaling_description ();
void setup_notebook_size ();
void setup_frame_rate_description ();
+ void setup_minimum_audio_channels ();
wxControl* video_control (wxControl *);
wxControl* still_control (wxControl *);
@@ -169,6 +172,8 @@ private:
wxStaticText* _source_frame_rate;
wxChoice* _dcp_frame_rate;
wxButton* _best_dcp_frame_rate;
+ wxCheckBox* _pad_with_silence;
+ wxSpinCtrl* _minimum_audio_channels;
wxStaticText* _frame_rate_description;
/** The Film's length */
wxStaticText* _length;