Fix assertion failure when processors return fewer channels than the DCP has.
authorCarl Hetherington <cth@carlh.net>
Fri, 11 Sep 2015 21:29:28 +0000 (22:29 +0100)
committerCarl Hetherington <cth@carlh.net>
Fri, 11 Sep 2015 21:29:28 +0000 (22:29 +0100)
12 files changed:
ChangeLog
src/lib/analyse_audio_job.h
src/lib/audio_point.h
src/lib/audio_processor.h
src/lib/mid_side_decoder.cc
src/lib/mid_side_decoder.h
src/lib/player.cc
src/lib/upmixer_a.cc
src/lib/upmixer_a.h
test/audio_processor_test.cc [new file with mode: 0644]
test/data
test/wscript

index cbf031b..fe02e25 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,8 @@
+2015-09-11  Carl Hetherington  <cth@carlh.net>
+
+       * Fix assertion failure when creating 6-channel DCPs
+       using the mid-side processor.
+
 2015-09-10  Carl Hetherington  <cth@carlh.net>
 
        * Version 2.1.62 released.
index 4273c19..d484bff 100644 (file)
@@ -22,6 +22,7 @@
  */
 
 #include "job.h"
+#include "audio_point.h"
 #include "types.h"
 
 class AudioBuffers;
index f699233..de8538e 100644 (file)
@@ -17,6 +17,9 @@
 
 */
 
+#ifndef DCPOMATIC_AUDIO_POINT_H
+#define DCPOMATIC_AUDIO_POINT_H
+
 #include <libcxml/cxml.h>
 
 namespace xmlpp {
@@ -46,3 +49,5 @@ public:
 private:
        float _data[COUNT];
 };
+
+#endif
index 114756f..2c66d5b 100644 (file)
@@ -54,8 +54,8 @@ public:
        virtual int out_channels () const = 0;
        /** @return A clone of this AudioProcessor for operation at the specified sampling rate */
        virtual boost::shared_ptr<AudioProcessor> clone (int sampling_rate) const = 0;
-       /** Process some data, returning the processed result */
-       virtual boost::shared_ptr<AudioBuffers> run (boost::shared_ptr<const AudioBuffers>) = 0;
+       /** Process some data, returning the processed result truncated or padded to `channels' */
+       virtual boost::shared_ptr<AudioBuffers> run (boost::shared_ptr<const AudioBuffers>, int channels) = 0;
        virtual void flush () {}
        /** Make the supplied audio mapping into a sensible default for this processor */
        virtual void make_audio_mapping_default (AudioMapping& mapping) const = 0;
index 842d5c8..4f619ad 100644 (file)
@@ -59,16 +59,27 @@ MidSideDecoder::clone (int) const
 }
 
 shared_ptr<AudioBuffers>
-MidSideDecoder::run (shared_ptr<const AudioBuffers> in)
+MidSideDecoder::run (shared_ptr<const AudioBuffers> in, int channels)
 {
-       shared_ptr<AudioBuffers> out (new AudioBuffers (3, in->frames ()));
+       int const N = min (channels, 3);
+       shared_ptr<AudioBuffers> out (new AudioBuffers (channels, in->frames ()));
        for (int i = 0; i < in->frames(); ++i) {
                float const left = in->data()[0][i];
                float const right = in->data()[1][i];
                float const mid = (left + right) / 2;
-               out->data()[0][i] = left - mid;
-               out->data()[1][i] = right - mid;
-               out->data()[2][i] = mid;
+               if (N > 0) {
+                       out->data()[0][i] = left - mid;
+               }
+               if (N > 1) {
+                       out->data()[1][i] = right - mid;
+               }
+               if (N > 2) {
+                       out->data()[2][i] = mid;
+               }
+       }
+
+       for (int i = N; i < channels; ++i) {
+               out->make_silent (i);
        }
 
        return out;
index 197c7b3..13e5ca3 100644 (file)
@@ -27,7 +27,7 @@ public:
        ChannelCount in_channels () const;
        int out_channels () const;
        boost::shared_ptr<AudioProcessor> clone (int) const;
-       boost::shared_ptr<AudioBuffers> run (boost::shared_ptr<const AudioBuffers>);
+       boost::shared_ptr<AudioBuffers> run (boost::shared_ptr<const AudioBuffers>, int channels);
        void make_audio_mapping_default (AudioMapping& mapping) const;
        std::vector<std::string> input_names () const;
 };
index 302ab16..acf977d 100644 (file)
@@ -508,7 +508,7 @@ Player::get_audio (DCPTime time, DCPTime length, bool accurate)
                        }
 
                        if (_audio_processor) {
-                               dcp_mapped = _audio_processor->run (dcp_mapped);
+                               dcp_mapped = _audio_processor->run (dcp_mapped, _film->audio_channels ());
                        }
 
                        all.audio = dcp_mapped;
index 1edc010..e6ec09c 100644 (file)
@@ -71,7 +71,7 @@ UpmixerA::clone (int sampling_rate) const
 }
 
 shared_ptr<AudioBuffers>
-UpmixerA::run (shared_ptr<const AudioBuffers> in)
+UpmixerA::run (shared_ptr<const AudioBuffers> in, int channels)
 {
        /* Input L and R */
        shared_ptr<AudioBuffers> in_L = in->channel (0);
@@ -83,20 +83,25 @@ UpmixerA::run (shared_ptr<const AudioBuffers> in)
        in_LR->apply_gain (0.5);
 
        /* Run filters */
-       shared_ptr<AudioBuffers> L = _left.run (in_L);
-       shared_ptr<AudioBuffers> R = _right.run (in_R);
-       shared_ptr<AudioBuffers> C = _centre.run (in_LR);
-       shared_ptr<AudioBuffers> Lfe = _lfe.run (in_LR);
-       shared_ptr<AudioBuffers> Ls = _ls.run (in_L);
-       shared_ptr<AudioBuffers> Rs = _rs.run (in_R);
-
-       shared_ptr<AudioBuffers> out (new AudioBuffers (6, in->frames ()));
-       out->copy_channel_from (L.get(), 0, 0);
-       out->copy_channel_from (R.get(), 0, 1);
-       out->copy_channel_from (C.get(), 0, 2);
-       out->copy_channel_from (Lfe.get(), 0, 3);
-       out->copy_channel_from (Ls.get(), 0, 4);
-       out->copy_channel_from (Rs.get(), 0, 5);
+       vector<shared_ptr<AudioBuffers> > all_out;
+       all_out.push_back (_left.run (in_L));
+       all_out.push_back (_right.run (in_R));
+       all_out.push_back (_centre.run (in_LR));
+       all_out.push_back (_lfe.run (in_LR));
+       all_out.push_back (_ls.run (in_L));
+       all_out.push_back (_rs.run (in_R));
+
+       shared_ptr<AudioBuffers> out (new AudioBuffers (channels, in->frames ()));
+       int const N = min (channels, 6);
+
+       for (int i = 0; i < N; ++i) {
+               out->copy_channel_from (all_out[i].get(), 0, i);
+       }
+
+       for (int i = N; i < channels; ++i) {
+               out->make_silent (i);
+       }
+
        return out;
 }
 
index 389d52d..a25c3a3 100644 (file)
@@ -37,7 +37,7 @@ public:
        ChannelCount in_channels () const;
        int out_channels () const;
        boost::shared_ptr<AudioProcessor> clone (int) const;
-       boost::shared_ptr<AudioBuffers> run (boost::shared_ptr<const AudioBuffers>);
+       boost::shared_ptr<AudioBuffers> run (boost::shared_ptr<const AudioBuffers>, int channels);
        void flush ();
        void make_audio_mapping_default (AudioMapping& mapping) const;
        std::vector<std::string> input_names () const;
diff --git a/test/audio_processor_test.cc b/test/audio_processor_test.cc
new file mode 100644 (file)
index 0000000..a668a7e
--- /dev/null
@@ -0,0 +1,53 @@
+/*
+    Copyright (C) 2015 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
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+*/
+
+#include "lib/audio_processor.h"
+#include "lib/analyse_audio_job.h"
+#include "lib/dcp_content_type.h"
+#include "lib/job_manager.h"
+#include "lib/sndfile_content.h"
+#include "lib/film.h"
+#include "test.h"
+#include <boost/test/unit_test.hpp>
+
+using boost::shared_ptr;
+
+/** Test the mid-side decoder for analysis and DCP-making */
+BOOST_AUTO_TEST_CASE (audio_processor_test)
+{
+       shared_ptr<Film> film = new_test_film ("audio_processor_test");
+       film->set_name ("audio_processor_test");
+       shared_ptr<SndfileContent> c (new SndfileContent (film, "test/data/white.wav"));
+       film->examine_and_add_content (c);
+       wait_for_jobs ();
+
+       film->set_audio_channels (6);
+       film->set_dcp_content_type (DCPContentType::from_pretty_name ("Test"));
+       film->set_audio_processor (AudioProcessor::from_id ("mid-side-decoder"));
+
+       /* Analyse the audio and check it doesn't crash */
+       shared_ptr<AnalyseAudioJob> job (new AnalyseAudioJob (film, film->playlist ()));
+       JobManager::instance()->add (job);
+       wait_for_jobs ();
+
+       /* Make a DCP and check it */
+       film->make_dcp ();
+       wait_for_jobs ();
+       check_dcp ("test/data/audio_processor_test", film->dir (film->dcp_name ()));
+}
index 8d1220d..2af14aa 160000 (submodule)
--- a/test/data
+++ b/test/data
@@ -1 +1 @@
-Subproject commit 8d1220d25c278d0a9678ccb0d0a07196a8f1331d
+Subproject commit 2af14aa5d93b321455e946af9b278ffd11db71b3
index f46d3dc..8707c15 100644 (file)
@@ -43,6 +43,7 @@ def build(bld):
                  audio_decoder_test.cc
                  audio_filter_test.cc
                  audio_mapping_test.cc
+                 audio_processor_test.cc
                  black_fill_test.cc
                  client_server_test.cc
                  colour_conversion_test.cc