summaryrefslogtreecommitdiff
path: root/src/lib
diff options
context:
space:
mode:
authorCarl Hetherington <cth@carlh.net>2013-07-25 22:04:20 +0100
committerCarl Hetherington <cth@carlh.net>2013-07-25 22:04:20 +0100
commit78e5a331074a456097a162d47501daf1df1ab1a3 (patch)
tree17dbc6cd0e3e6a4878277959d7cd86129fb516b4 /src/lib
parent991244a0d4be149e8733a8dd70bfd745cab72583 (diff)
Hopefully much cleaner handling of PTS changes under resample.
Diffstat (limited to 'src/lib')
-rw-r--r--src/lib/audio_decoder.cc28
-rw-r--r--src/lib/audio_decoder.h7
-rw-r--r--src/lib/ffmpeg_decoder.cc4
-rw-r--r--src/lib/player.cc40
-rw-r--r--src/lib/player.h3
-rw-r--r--src/lib/resampler.cc10
-rw-r--r--src/lib/resampler.h4
-rw-r--r--src/lib/sndfile_decoder.cc2
8 files changed, 60 insertions, 38 deletions
diff --git a/src/lib/audio_decoder.cc b/src/lib/audio_decoder.cc
index 846cdf595..1f5868583 100644
--- a/src/lib/audio_decoder.cc
+++ b/src/lib/audio_decoder.cc
@@ -32,36 +32,16 @@ using std::cout;
using boost::optional;
using boost::shared_ptr;
-AudioDecoder::AudioDecoder (shared_ptr<const Film> film, shared_ptr<const AudioContent> content)
+AudioDecoder::AudioDecoder (shared_ptr<const Film> film)
: Decoder (film)
, _audio_position (0)
{
- if (content->content_audio_frame_rate() != content->output_audio_frame_rate() && content->audio_channels ()) {
- _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)
-{
- if (_resampler) {
- data = _resampler->run (data);
- }
- Audio (data, _audio_position);
- _audio_position += data->frames ();
}
void
-AudioDecoder::flush ()
+AudioDecoder::audio (shared_ptr<const AudioBuffers> data, AudioContent::Frame frame)
{
- if (_resampler) {
- _resampler->flush ();
- }
+ Audio (data, frame);
+ _audio_position = frame + data->frames ();
}
diff --git a/src/lib/audio_decoder.h b/src/lib/audio_decoder.h
index e2d28d707..2ad53da8b 100644
--- a/src/lib/audio_decoder.h
+++ b/src/lib/audio_decoder.h
@@ -29,7 +29,6 @@
#include "audio_content.h"
class AudioBuffers;
-class Resampler;
/** @class AudioDecoder.
* @brief Parent class for audio decoders.
@@ -37,19 +36,15 @@ class Resampler;
class AudioDecoder : public virtual Decoder
{
public:
- AudioDecoder (boost::shared_ptr<const Film>, boost::shared_ptr<const AudioContent>);
+ AudioDecoder (boost::shared_ptr<const Film>);
/** Emitted when some audio data is ready */
boost::signals2::signal<void (boost::shared_ptr<const AudioBuffers>, AudioContent::Frame)> Audio;
protected:
- void flush ();
-
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
diff --git a/src/lib/ffmpeg_decoder.cc b/src/lib/ffmpeg_decoder.cc
index e2e5b9d64..58745598a 100644
--- a/src/lib/ffmpeg_decoder.cc
+++ b/src/lib/ffmpeg_decoder.cc
@@ -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, c)
+ , AudioDecoder (f)
, SubtitleDecoder (f)
, FFmpeg (c)
, _subtitle_codec_context (0)
@@ -140,8 +140,6 @@ FFmpegDecoder::flush ()
decode_audio_packet ();
}
- AudioDecoder::flush ();
-
/* Stop us being asked for any more data */
_video_position = _ffmpeg_content->video_length ();
_audio_position = _ffmpeg_content->audio_length ();
diff --git a/src/lib/player.cc b/src/lib/player.cc
index 1ab164d86..620efbd0d 100644
--- a/src/lib/player.cc
+++ b/src/lib/player.cc
@@ -31,6 +31,7 @@
#include "job.h"
#include "image.h"
#include "ratio.h"
+#include "resampler.h"
#include "log.h"
#include "scaler.h"
@@ -190,6 +191,19 @@ 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;
}
@@ -264,6 +278,14 @@ 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);
+ pair<shared_ptr<const AudioBuffers>, AudioContent::Frame> ro = r->run (audio, frame);
+ audio = ro.first;
+ frame = ro.second;
+ }
+
/* Remap channels */
shared_ptr<AudioBuffers> dcp_mapped (new AudioBuffers (_film->audio_channels(), audio->frames()));
dcp_mapped->make_silent ();
@@ -314,6 +336,7 @@ Player::process_audio (weak_ptr<Piece> weak_piece, shared_ptr<const AudioBuffers
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 = _audio_position + _film->audio_frames_to_time (N);
/* And remove it from our buffers */
@@ -497,6 +520,23 @@ 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 ()
{
diff --git a/src/lib/player.h b/src/lib/player.h
index 5b1b6936b..cd480dd1a 100644
--- a/src/lib/player.h
+++ b/src/lib/player.h
@@ -35,6 +35,7 @@ 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.
@@ -89,6 +90,7 @@ 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 ();
@@ -111,6 +113,7 @@ private:
libdcp::Size _video_container_size;
boost::shared_ptr<Image> _black_frame;
+ std::map<boost::shared_ptr<AudioContent>, boost::shared_ptr<Resampler> > _resamplers;
struct {
boost::weak_ptr<Piece> piece;
diff --git a/src/lib/resampler.cc b/src/lib/resampler.cc
index cc5072442..7bc933fd0 100644
--- a/src/lib/resampler.cc
+++ b/src/lib/resampler.cc
@@ -27,6 +27,8 @@ extern "C" {
#include "i18n.h"
using std::cout;
+using std::pair;
+using std::make_pair;
using boost::shared_ptr;
Resampler::Resampler (int in, int out, int channels)
@@ -61,9 +63,11 @@ Resampler::~Resampler ()
swr_free (&_swr_context);
}
-shared_ptr<const AudioBuffers>
-Resampler::run (shared_ptr<const AudioBuffers> in)
+pair<shared_ptr<const AudioBuffers>, AudioContent::Frame>
+Resampler::run (shared_ptr<const AudioBuffers> in, AudioContent::Frame frame)
{
+ AudioContent::Frame const resamp_time = swr_next_pts (_swr_context, frame * _out_rate) / _in_rate;
+
/* Compute the resampled frames count and add 32 for luck */
int const max_resampled_frames = ceil ((double) in->frames() * _out_rate / _in_rate) + 32;
shared_ptr<AudioBuffers> resampled (new AudioBuffers (_channels, max_resampled_frames));
@@ -77,7 +81,7 @@ Resampler::run (shared_ptr<const AudioBuffers> in)
}
resampled->set_frames (resampled_frames);
- return resampled;
+ return make_pair (resampled, resamp_time);
}
shared_ptr<const AudioBuffers>
diff --git a/src/lib/resampler.h b/src/lib/resampler.h
index 6e282838a..69ec83ba9 100644
--- a/src/lib/resampler.h
+++ b/src/lib/resampler.h
@@ -22,6 +22,8 @@
extern "C" {
#include <libswresample/swresample.h>
}
+#include "types.h"
+#include "audio_content.h"
class AudioBuffers;
@@ -31,7 +33,7 @@ public:
Resampler (int, int, int);
~Resampler ();
- boost::shared_ptr<const AudioBuffers> run (boost::shared_ptr<const AudioBuffers>);
+ std::pair<boost::shared_ptr<const AudioBuffers>, AudioContent::Frame> run (boost::shared_ptr<const AudioBuffers>, AudioContent::Frame);
boost::shared_ptr<const AudioBuffers> flush ();
private:
diff --git a/src/lib/sndfile_decoder.cc b/src/lib/sndfile_decoder.cc
index 09ccf4fbc..1fc1ecaf2 100644
--- a/src/lib/sndfile_decoder.cc
+++ b/src/lib/sndfile_decoder.cc
@@ -35,7 +35,7 @@ using boost::shared_ptr;
SndfileDecoder::SndfileDecoder (shared_ptr<const Film> f, shared_ptr<const SndfileContent> c)
: Decoder (f)
- , AudioDecoder (f, c)
+ , AudioDecoder (f)
, _sndfile_content (c)
, _deinterleave_buffer (0)
{