Move resampling back into AudioDecoder and fix various screw-ups with audio in the...
authorCarl Hetherington <cth@carlh.net>
Thu, 25 Jul 2013 12:26:40 +0000 (13:26 +0100)
committerCarl Hetherington <cth@carlh.net>
Thu, 25 Jul 2013 12:26:40 +0000 (13:26 +0100)
src/lib/audio_decoder.cc
src/lib/audio_decoder.h
src/lib/ffmpeg_decoder.cc
src/lib/job.cc
src/lib/job.h
src/lib/player.cc
src/lib/player.h
src/lib/sndfile_decoder.cc

index 59c631632f3f63b735a883dd1292c46403e4ec64..0ed3505cf2aa959c93c06e9c4d16528a5e36bb16 100644 (file)
@@ -21,6 +21,7 @@
 #include "audio_buffers.h"
 #include "exceptions.h"
 #include "log.h"
+#include "resampler.h"
 
 #include "i18n.h"
 
@@ -31,16 +32,30 @@ using std::cout;
 using boost::optional;
 using boost::shared_ptr;
 
-AudioDecoder::AudioDecoder (shared_ptr<const Film> f)
-       : Decoder (f)
+AudioDecoder::AudioDecoder (shared_ptr<const Film> film, shared_ptr<const AudioContent> content)
+       : Decoder (film)
        , _audio_position (0)
 {
-
+       if (content->content_audio_frame_rate() != content->output_audio_frame_rate()) {
+               _resampler.reset (
+                       new Resampler (
+                               content->content_audio_frame_rate(),
+                               content->output_audio_frame_rate(),
+                               content->audio_channels()
+                               )
+                       );
+       }
 }
 
 void
 AudioDecoder::audio (shared_ptr<const AudioBuffers> data, AudioContent::Frame frame)
 {
-       Audio (data, frame);
+       /* XXX: no-one's calling _resampler->flush() again */
+       
+       if (_resampler) {
+               data = _resampler->run (data);
+       } 
+
+       Audio (data, _audio_position);
        _audio_position = frame + data->frames ();
 }
index 2ad53da8bf42684e544e753bc6b0ca4708c72d19..b1ec54a7b40fa5683a9ac75f20366db70bc34690 100644 (file)
@@ -29,6 +29,7 @@
 #include "audio_content.h"
 
 class AudioBuffers;
+class Resampler;
 
 /** @class AudioDecoder.
  *  @brief Parent class for audio decoders.
@@ -36,7 +37,7 @@ class AudioBuffers;
 class AudioDecoder : public virtual Decoder
 {
 public:
-       AudioDecoder (boost::shared_ptr<const Film>);
+       AudioDecoder (boost::shared_ptr<const Film>, boost::shared_ptr<const AudioContent>);
 
        /** Emitted when some audio data is ready */
        boost::signals2::signal<void (boost::shared_ptr<const AudioBuffers>, AudioContent::Frame)> Audio;
@@ -44,7 +45,9 @@ public:
 protected:
 
        void audio (boost::shared_ptr<const AudioBuffers>, AudioContent::Frame);
+       /** Frame index of next emission (post resampling) */
        AudioContent::Frame _audio_position;
+       boost::shared_ptr<Resampler> _resampler;
 };
 
 #endif
index 8329cad65b4156b02559cb40dbb3c2829145a133..d8319723a3538f03cdb6bb94fe3ec41cb1082287 100644 (file)
@@ -60,7 +60,7 @@ using libdcp::Size;
 FFmpegDecoder::FFmpegDecoder (shared_ptr<const Film> f, shared_ptr<const FFmpegContent> c, bool video, bool audio)
        : Decoder (f)
        , VideoDecoder (f, c)
-       , AudioDecoder (f)
+       , AudioDecoder (f, c)
        , SubtitleDecoder (f)
        , FFmpeg (c)
        , _subtitle_codec_context (0)
index e63ea6dc8e16776099580cb3740a5b46c7061d0b..12dc88fbc02aa0c0ce518d0db1c543abef9258ab 100644 (file)
@@ -34,6 +34,7 @@
 
 using std::string;
 using std::list;
+using std::cout;
 using std::stringstream;
 using boost::shared_ptr;
 
@@ -43,6 +44,7 @@ Job::Job (shared_ptr<const Film> f)
        , _state (NEW)
        , _start_time (0)
        , _progress_unknown (false)
+       , _last_set (0)
        , _ran_for (0)
 {
        descend (1);
@@ -213,6 +215,13 @@ Job::elapsed_time () const
 void
 Job::set_progress (float p)
 {
+       if (fabs (p - _last_set) < 0.01) {
+               /* Calm excessive progress reporting */
+               return;
+       }
+
+       _last_set = p;
+
        boost::mutex::scoped_lock lm (_progress_mutex);
        _progress_unknown = false;
        _stack.back().normalised = p;
index 343d400958b0864caa46d9cbf2226e3c3ece5cbd..eb09ba386509cf33398fe6628c67ca863ff0ca78 100644 (file)
@@ -126,6 +126,8 @@ private:
        /** true if this job's progress will always be unknown */
        bool _progress_unknown;
 
+       float _last_set;
+
        int _ran_for;
 };
 
index 8cc1849e865f0909001a55374954bca5fbe48247..1ab164d867f216f80c44bb0dd8c4e5c24fd9b0ad 100644 (file)
@@ -31,7 +31,6 @@
 #include "job.h"
 #include "image.h"
 #include "ratio.h"
-#include "resampler.h"
 #include "log.h"
 #include "scaler.h"
 
@@ -191,18 +190,6 @@ Player::pass ()
                        cout << "Pass " << *earliest << "\n";
 #endif                 
                        earliest->decoder->pass ();
-                       
-                       if (earliest->decoder->done()) {
-                               shared_ptr<AudioContent> ac = dynamic_pointer_cast<AudioContent> (earliest->content);
-                               assert (ac);
-                               shared_ptr<Resampler> re = resampler (ac, false);
-                               if (re) {
-                                       shared_ptr<const AudioBuffers> b = re->flush ();
-                                       if (b->frames ()) {
-                                               process_audio (earliest, b, ac->audio_length ());
-                                       }
-                               }
-                       }
                }
                break;
        }
@@ -277,12 +264,6 @@ Player::process_audio (weak_ptr<Piece> weak_piece, shared_ptr<const AudioBuffers
        shared_ptr<AudioContent> content = dynamic_pointer_cast<AudioContent> (piece->content);
        assert (content);
 
-       /* Resample */
-       if (content->content_audio_frame_rate() != content->output_audio_frame_rate()) {
-               shared_ptr<Resampler> r = resampler (content, true);
-               audio = r->run (audio);
-       }
-
        /* Remap channels */
        shared_ptr<AudioBuffers> dcp_mapped (new AudioBuffers (_film->audio_channels(), audio->frames()));
        dcp_mapped->make_silent ();
@@ -295,10 +276,9 @@ Player::process_audio (weak_ptr<Piece> weak_piece, shared_ptr<const AudioBuffers
 
        audio = dcp_mapped;
 
-       /* Convert frame to time.  After resampling, the frame time (in the DCP rate) will be T_D where
-          T_D = frame * DCP_rate / original_rate.  Hence the time in seconds is T_D / DCP_rate.
-       */
-       Time time = content->start() + (frame * TIME_HZ / _film->audio_frame_rate()) + (content->audio_delay() * TIME_HZ / 1000);
+       Time time = content->start()
+               + _film->audio_frames_to_time (frame)
+               + (content->audio_delay() * TIME_HZ / 1000);
 
        /* We must cut off anything that comes before the start of all time */
        if (time < 0) {
@@ -319,7 +299,7 @@ Player::process_audio (weak_ptr<Piece> weak_piece, shared_ptr<const AudioBuffers
        */
 
        if (time > _audio_position) {
-               /* We can emit some audio from our buffers */
+               /* We can emit some audio from our buffers; this is how many frames */
                OutputAudioFrame const N = _film->time_to_audio_frames (time - _audio_position);
                if (N > _audio_buffers.frames()) {
                        /* We need some extra silence before whatever is in the buffers */
@@ -329,10 +309,12 @@ Player::process_audio (weak_ptr<Piece> weak_piece, shared_ptr<const AudioBuffers
                        _audio_buffers.set_frames (N);
                }
                assert (N <= _audio_buffers.frames());
+
+               /* XXX: not convinced that a copy is necessary here */
                shared_ptr<AudioBuffers> emit (new AudioBuffers (_audio_buffers.channels(), N));
                emit->copy_from (&_audio_buffers, N, 0, 0);
                Audio (emit, _audio_position);
-               _audio_position = piece->audio_position = time + _film->audio_frames_to_time (N);
+               _audio_position = piece->audio_position = _audio_position + _film->audio_frames_to_time (N);
 
                /* And remove it from our buffers */
                if (_audio_buffers.frames() > N) {
@@ -515,23 +497,6 @@ Player::set_video_container_size (libdcp::Size s)
        _black_frame->make_black ();
 }
 
-shared_ptr<Resampler>
-Player::resampler (shared_ptr<AudioContent> c, bool create)
-{
-       map<shared_ptr<AudioContent>, shared_ptr<Resampler> >::iterator i = _resamplers.find (c);
-       if (i != _resamplers.end ()) {
-               return i->second;
-       }
-
-       if (!create) {
-               return shared_ptr<Resampler> ();
-       }
-       
-       shared_ptr<Resampler> r (new Resampler (c->content_audio_frame_rate(), c->output_audio_frame_rate(), c->audio_channels()));
-       _resamplers[c] = r;
-       return r;
-}
-
 void
 Player::emit_black ()
 {
index baaa8579166a0837be3e8f3a4783b662941f8b43..5b1b6936bc95a41ca548fef98f32cc146da9a628 100644 (file)
@@ -35,7 +35,6 @@ class Playlist;
 class AudioContent;
 class Piece;
 class Image;
-class Resampler;
 
 /** @class Player
  *  @brief A class which can `play' a Playlist; emitting its audio and video.
@@ -90,7 +89,6 @@ private:
        void flush ();
        void emit_black ();
        void emit_silence (OutputAudioFrame);
-       boost::shared_ptr<Resampler> resampler (boost::shared_ptr<AudioContent>, bool);
        void film_changed (Film::Property);
        void update_subtitle ();
 
@@ -113,8 +111,6 @@ private:
 
        libdcp::Size _video_container_size;
        boost::shared_ptr<Image> _black_frame;
-       std::map<boost::shared_ptr<AudioContent>, boost::shared_ptr<Resampler> > _resamplers;
-       boost::shared_ptr<Resampler> _last_resampler;
 
        struct {
                boost::weak_ptr<Piece> piece;
index 1fc1ecaf2cc66c1cbcb650f0af9cad0f0d2a82fc..09ccf4fbc1fd9ba5d2bcf3eac9d3aa2ae135b45b 100644 (file)
@@ -35,7 +35,7 @@ using boost::shared_ptr;
 
 SndfileDecoder::SndfileDecoder (shared_ptr<const Film> f, shared_ptr<const SndfileContent> c)
        : Decoder (f)
-       , AudioDecoder (f)
+       , AudioDecoder (f, c)
        , _sndfile_content (c)
        , _deinterleave_buffer (0)
 {