Partial addition of DCP audio channel count to Film.
authorCarl Hetherington <cth@carlh.net>
Fri, 24 May 2013 21:00:53 +0000 (22:00 +0100)
committerCarl Hetherington <cth@carlh.net>
Fri, 24 May 2013 21:00:53 +0000 (22:00 +0100)
src/lib/analyse_audio_job.cc
src/lib/audio_buffers.cc
src/lib/audio_buffers.h
src/lib/audio_decoder.cc
src/lib/film.cc
src/lib/film.h
src/lib/null_content.cc
src/lib/null_content.h
src/lib/player.cc
src/lib/silence_decoder.cc
src/lib/writer.cc

index 13cab1a469902f9c31a1d3700258ebe420fb96c4..3a44a408fe2aec93cb1869f30d044ac90874ef32 100644 (file)
@@ -57,8 +57,8 @@ AnalyseAudioJob::run ()
 
        _samples_per_point = max (int64_t (1), _film->time_to_audio_frames (_film->length()) / _num_points);
 
-       _current.resize (MAX_AUDIO_CHANNELS);
-       _analysis.reset (new AudioAnalysis (MAX_AUDIO_CHANNELS));
+       _current.resize (_film->dcp_audio_channels ());
+       _analysis.reset (new AudioAnalysis (_film->dcp_audio_channels ()));
 
        _done = 0;
        while (player->pass ()) {
index cd8fcd35be45ac3f7ecb1d4cee272f58f453f2eb..c3e89f1302e5315e01495c374a994975b19b806b 100644 (file)
@@ -193,7 +193,7 @@ AudioBuffers::move (int from, int to, int frames)
 
 /** Add data from from `from', `from_channel' to our channel `to_channel' */
 void
-AudioBuffers::accumulate (AudioBuffers const * from, int from_channel, int to_channel)
+AudioBuffers::accumulate_channel (AudioBuffers const * from, int from_channel, int to_channel)
 {
        int const N = frames ();
        assert (from->frames() == N);
@@ -214,9 +214,24 @@ AudioBuffers::ensure_size (int frames)
        }
 
        for (int i = 0; i < _channels; ++i) {
-               _data[i] = static_cast<float*> (realloc (_data[i], _frames * sizeof (float)));
+               _data[i] = static_cast<float*> (realloc (_data[i], frames * sizeof (float)));
                if (!_data[i]) {
                        throw bad_alloc ();
                }
        }
+
+       _allocated_frames = frames;
+}
+
+void
+AudioBuffers::accumulate_frames (AudioBuffers const * from, int read_offset, int write_offset, int frames)
+{
+       assert (_channels == from->channels ());
+
+       for (int i = 0; i < _channels; ++i) {
+               for (int j = 0; j < frames; ++j) {
+                       _data[i][j + write_offset] += from->data()[i][j + read_offset];
+               }
+       }
 }
+
index 5e7b9fda4e769889d4a819e8df168dfe186e8777..47b8145a1de2892e6126ca3cea8738a034514eff 100644 (file)
@@ -53,7 +53,8 @@ public:
 
        void copy_from (AudioBuffers const * from, int frames_to_copy, int read_offset, int write_offset);
        void move (int from, int to, int frames);
-       void accumulate (AudioBuffers const *, int, int);
+       void accumulate_channel (AudioBuffers const *, int, int);
+       void accumulate_frames (AudioBuffers const *, int read_offset, int write_offset, int frames);
 
 private:
        /** Number of channels */
index 6712e06241dc37a9e1c99fcaeb88c92c50f4d01d..8950e15465d3602673ff75bcae43f5f5e129a49c 100644 (file)
@@ -112,8 +112,6 @@ AudioDecoder::process_end ()
 void
 AudioDecoder::audio (shared_ptr<const AudioBuffers> data, Time time)
 {
-       /* XXX: map audio to 5.1 */
-       
        /* Maybe resample */
        if (_swr_context) {
 
@@ -122,7 +120,7 @@ AudioDecoder::audio (shared_ptr<const AudioBuffers> data, Time time)
                        (int64_t) data->frames() * _audio_content->output_audio_frame_rate() / _audio_content->content_audio_frame_rate()
                        ) + 32;
 
-               shared_ptr<AudioBuffers> resampled (new AudioBuffers (MAX_AUDIO_CHANNELS, max_resampled_frames));
+               shared_ptr<AudioBuffers> resampled (new AudioBuffers (data->channels(), max_resampled_frames));
 
                /* Resample audio */
                int const resampled_frames = swr_convert (
@@ -139,10 +137,18 @@ AudioDecoder::audio (shared_ptr<const AudioBuffers> data, Time time)
                data = resampled;
        }
 
-       Audio (data, time);
-
        shared_ptr<const Film> film = _film.lock ();
        assert (film);
+       
+       /* Remap channels */
+       shared_ptr<AudioBuffers> dcp_mapped (film->dcp_audio_channels(), data->frames());
+       dcp_mapped->make_silent ();
+       list<pair<int, libdcp::Channel> > map = _audio_content->audio_mapping().content_to_dcp ();
+       for (list<pair<int, libdcp::Channel> >::iterator i = map.begin(); i != map.end(); ++i) {
+               dcp_mapped->accumulate (data, i->first, i->second);
+       }
+
+       Audio (dcp_mapped, time);
        _next_audio = time + film->audio_frames_to_time (data->frames());
 }
 
index 9103024ab14d1fbc560743106bf2bc47abcff7e2..a61a0d53daaf5b140cc9c816d79a6232e2256f56 100644 (file)
@@ -102,6 +102,7 @@ Film::Film (string d)
        , _j2k_bandwidth (200000000)
        , _dci_metadata (Config::instance()->default_dci_metadata ())
        , _dcp_video_frame_rate (0)
+       , _dcp_audio_channels (MAX_AUDIO_CHANNELS)
        , _dirty (false)
 {
        set_dci_date_today ();
@@ -172,7 +173,7 @@ Film::video_state_identifier () const
          << "_" << f.first << "_" << f.second
          << "_" << scaler()->id()
          << "_" << j2k_bandwidth()
-         << "_" << boost::lexical_cast<int> (colour_lut());
+         << "_" << lexical_cast<int> (colour_lut());
 
        if (ab()) {
                pair<string, string> fa = Filter::ffmpeg_strings (Config::instance()->reference_filters());
@@ -382,7 +383,7 @@ Film::write_metadata () const
        xmlpp::Document doc;
        xmlpp::Element* root = doc.create_root_node ("Metadata");
 
-       root->add_child("Version")->add_child_text (boost::lexical_cast<string> (state_version));
+       root->add_child("Version")->add_child_text (lexical_cast<string> (state_version));
        root->add_child("Name")->add_child_text (_name);
        root->add_child("UseDCIName")->add_child_text (_use_dci_name ? "1" : "0");
 
@@ -401,13 +402,14 @@ Film::write_metadata () const
        root->add_child("Scaler")->add_child_text (_scaler->id ());
        root->add_child("AB")->add_child_text (_ab ? "1" : "0");
        root->add_child("WithSubtitles")->add_child_text (_with_subtitles ? "1" : "0");
-       root->add_child("SubtitleOffset")->add_child_text (boost::lexical_cast<string> (_subtitle_offset));
-       root->add_child("SubtitleScale")->add_child_text (boost::lexical_cast<string> (_subtitle_scale));
-       root->add_child("ColourLUT")->add_child_text (boost::lexical_cast<string> (_colour_lut));
-       root->add_child("J2KBandwidth")->add_child_text (boost::lexical_cast<string> (_j2k_bandwidth));
+       root->add_child("SubtitleOffset")->add_child_text (lexical_cast<string> (_subtitle_offset));
+       root->add_child("SubtitleScale")->add_child_text (lexical_cast<string> (_subtitle_scale));
+       root->add_child("ColourLUT")->add_child_text (lexical_cast<string> (_colour_lut));
+       root->add_child("J2KBandwidth")->add_child_text (lexical_cast<string> (_j2k_bandwidth));
        _dci_metadata.as_xml (root->add_child ("DCIMetadata"));
-       root->add_child("DCPVideoFrameRate")->add_child_text (boost::lexical_cast<string> (_dcp_video_frame_rate));
+       root->add_child("DCPVideoFrameRate")->add_child_text (lexical_cast<string> (_dcp_video_frame_rate));
        root->add_child("DCIDate")->add_child_text (boost::gregorian::to_iso_string (_dci_date));
+       root->add_child("DCPAudioChannels")->add_child_text (lexical_cast<string> (_dcp_audio_channels));
        _playlist->as_xml (root->add_child ("Playlist"));
 
        doc.write_to_file_formatted (file ("metadata.xml"));
@@ -462,6 +464,7 @@ Film::read_metadata ()
        _dci_metadata = DCIMetadata (f.node_child ("DCIMetadata"));
        _dcp_video_frame_rate = f.number_child<int> ("DCPVideoFrameRate");
        _dci_date = boost::gregorian::from_undelimited_string (f.string_child ("DCIDate"));
+       _dcp_audio_channels = f.number_child<int> ("DCPAudioChannels");
 
        _playlist->set_from_xml (shared_from_this(), f.node_child ("Playlist"));
 
index b8d4ee40e1b1cefbcc6e9aeffa5f14da4d915d3c..f0ccd99e77b33139b95ad23bc6d5678e18c4da9a 100644 (file)
@@ -103,6 +103,7 @@ public:
        boost::shared_ptr<Playlist> playlist () const;
 
        OutputAudioFrame dcp_audio_frame_rate () const;
+       int dcp_audio_channels () const;
 
        OutputAudioFrame time_to_audio_frames (Time) const;
        OutputVideoFrame time_to_video_frames (Time) const;
@@ -223,6 +224,11 @@ public:
                return _dcp_video_frame_rate;
        }
 
+       int dcp_audio_channels () const {
+               boost::mutex::scoped_lock lm (_state_mutex);
+               return _dcp_audio_channels;
+       }
+
        /* SET */
 
        void set_directory (std::string);
@@ -315,6 +321,7 @@ private:
        int _dcp_video_frame_rate;
        /** The date that we should use in a DCI name */
        boost::gregorian::date _dci_date;
+       int _dcp_audio_channels;
 
        /** true if our state has changed since we last saved it */
        mutable bool _dirty;
index 0084972c2ae5e5045000c8ae8cd297655e1a893b..3bbda92da1c36d615df10751193aaee36642e529 100644 (file)
@@ -46,3 +46,12 @@ NullContent::output_audio_frame_rate () const
        assert (film);
        return film->dcp_audio_frame_rate ();
 }
+
+int
+NullContent::audio_channels () const
+{
+       shared_ptr<const Film> film = _film.lock ();
+       assert (film);
+       return film->dcp_audio_channels ();
+}
+       
index d4a3b7371ed8514b75372cc08626784939686b71..f8829658c5b403aca8e6f807430c09538684dd1a 100644 (file)
@@ -41,9 +41,7 @@ public:
                return boost::shared_ptr<Content> ();
        }
 
-        int audio_channels () const {
-               return MAX_AUDIO_CHANNELS;
-       }
+        int audio_channels () const;
        
         ContentAudioFrame audio_length () const {
                return _audio_length;
index d3886721b1849b47aff45ffd781a364c8cac0508..032b3d49bcc897129d99d5ddd7b6c53448908880 100644 (file)
@@ -62,7 +62,7 @@ Player::Player (shared_ptr<const Film> f, shared_ptr<const Playlist> p)
        , _subtitles (true)
        , _have_valid_pieces (false)
        , _position (0)
-       , _audio_buffers (MAX_AUDIO_CHANNELS, 0)
+       , _audio_buffers (f->dcp_audio_channels(), 0)
        , _next_audio (0)
 {
        _playlist->Changed.connect (bind (&Player::playlist_changed, this));
@@ -164,8 +164,6 @@ Player::process_audio (weak_ptr<Content> weak_content, shared_ptr<const AudioBuf
                return;
        }
        
-        /* XXX: mapping */
-
         /* The time of this audio may indicate that some of our buffered audio is not going to
            be added to any more, so it can be emitted.
         */
@@ -174,7 +172,8 @@ Player::process_audio (weak_ptr<Content> weak_content, shared_ptr<const AudioBuf
 
         if (time > _next_audio) {
                 /* We can emit some audio from our buffers */
-                OutputAudioFrame const N = min (_film->time_to_audio_frames (time - _next_audio), static_cast<OutputAudioFrame> (_audio_buffers.frames()));
+               assert (_film->time_to_audio_frames (time - _next_audio) <= _audio_buffers.frames());
+                OutputAudioFrame const N = _film->time_to_audio_frames (time - _next_audio);
                 shared_ptr<AudioBuffers> emit (new AudioBuffers (_audio_buffers.channels(), N));
                 emit->copy_from (&_audio_buffers, N, 0, 0);
                 Audio (emit, _next_audio);
@@ -188,8 +187,8 @@ Player::process_audio (weak_ptr<Content> weak_content, shared_ptr<const AudioBuf
         }
 
         /* Now accumulate the new audio into our buffers */
-        _audio_buffers.ensure_size (time - _next_audio + audio->frames());
-        _audio_buffers.accumulate (audio.get(), 0, _film->time_to_audio_frames (time - _next_audio));
+        _audio_buffers.ensure_size (_audio_buffers.frames() + audio->frames());
+        _audio_buffers.accumulate_frames (audio, 0, 0, audio->frames ());
 }
 
 /** @return true on error */
index e787262f5054510e6b4117ee96e6e8a5691b53ae..6cf91b41fee15f6f02226d7cb0c30baeac1cd144 100644 (file)
@@ -38,7 +38,7 @@ SilenceDecoder::pass ()
        assert (film);
        
        Time const this_time = min (_audio_content->length() - _next_audio, TIME_HZ / 2);
-       shared_ptr<AudioBuffers> data (new AudioBuffers (MAX_AUDIO_CHANNELS, film->time_to_audio_frames (this_time)));
+       shared_ptr<AudioBuffers> data (new AudioBuffers (film->dcp_audio_channels(), film->time_to_audio_frames (this_time)));
        data->make_silent ();
        audio (data, _next_audio);
 }
index aef7230dd0834ae735e55c7cc314acdc21ed95fb..39b9b9304ff5a49a1d9b29f9f75d30fa38ca3eda 100644 (file)
@@ -87,7 +87,7 @@ Writer::Writer (shared_ptr<Film> f, shared_ptr<Job> j)
                        _film->dir (_film->dcp_name()),
                        _film->dcp_audio_mxf_filename (),
                        _film->dcp_video_frame_rate (),
-                       MAX_AUDIO_CHANNELS,
+                       _film->dcp_audio_channels (),
                        _film->dcp_audio_frame_rate()
                        )
                );