AudioDecoder::AudioDecoder (shared_ptr<const Film> film, shared_ptr<const AudioContent> content)
: Decoder (film)
, _audio_content (content)
+ , _last_audio (0)
{
-
+ if (content->output_audio_frame_rate() != content->content_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, ContentTime time)
{
+ if (_resampler) {
+ data = _resampler->run (data);
+ }
+
_pending.push_back (shared_ptr<DecodedAudio> (new DecodedAudio (data, time)));
+ _last_audio = time + (data->frames() * TIME_HZ / _audio_content->output_audio_frame_rate());
+}
+
+void
+AudioDecoder::flush ()
+{
+ if (!_resampler) {
+ return;
+ }
+
+ shared_ptr<const AudioBuffers> b = _resampler->flush ();
+ if (b) {
+ audio (b, _last_audio);
+ }
}
#include "decoded.h"
class AudioBuffers;
+class Resampler;
/** @class AudioDecoder.
* @brief Parent class for audio decoders.
{
public:
AudioDecoder (boost::shared_ptr<const Film>, boost::shared_ptr<const AudioContent>);
-
+
boost::shared_ptr<const AudioContent> audio_content () const {
return _audio_content;
}
protected:
void audio (boost::shared_ptr<const AudioBuffers>, ContentTime);
-
- boost::shared_ptr<const AudioContent> _audio_content;
+ void flush ();
+
+ boost::shared_ptr<const AudioContent> _audio_content;
+ boost::shared_ptr<Resampler> _resampler;
+ /* End time of last audio that we wrote to _pending; only used for flushing the resampler */
+ ContentTime _last_audio;
};
#endif
if (_ffmpeg_content->audio_stream() && _decode_audio) {
decode_audio_packet ();
}
+
+ AudioDecoder::flush ();
}
bool
#include "job.h"
#include "image.h"
#include "ratio.h"
-#include "resampler.h"
#include "log.h"
#include "scaler.h"
dec->set_dcp_times ((*i)->frc.speed_up, (*i)->content->position());
}
- /* XXX: don't know what to do with this */
-#if 0
- if (ad->done()) {
- shared_ptr<AudioContent> ac = dynamic_pointer_cast<AudioContent> ((*i)->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 ());
- }
- }
- }
-#endif
-
if (dec && dec->dcp_time < earliest_time) {
earliest_piece = *i;
earliest_decoded = dec;
audio->data = gain;
}
- /* Resample */
- if (content->content_audio_frame_rate() != content->output_audio_frame_rate()) {
- audio->data = resampler(content, true)->run (audio->data);
- }
-
if (content->trimmed (audio->dcp_time - content->position ())) {
return;
}
);
}
-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> ();
- }
-
- _film->log()->log (
- String::compose (
- "Creating new resampler for %1 to %2 with %3 channels", c->content_audio_frame_rate(), c->output_audio_frame_rate(), c->audio_channels()
- )
- );
-
- 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 ()
{
class AudioContent;
class Piece;
class Image;
-class Resampler;
/** @class PlayerImage
* @brief A wrapper for an Image which contains some pending operations; these may
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 ();
void emit_video (boost::weak_ptr<Piece>, boost::shared_ptr<DecodedVideo>);
libdcp::Size _video_container_size;
boost::shared_ptr<PlayerImage> _black_frame;
- std::map<boost::shared_ptr<AudioContent>, boost::shared_ptr<Resampler> > _resamplers;
struct {
boost::weak_ptr<Piece> piece;