using std::map;
using boost::shared_ptr;
-AudioDecoder::AudioDecoder (Decoder* parent, shared_ptr<const AudioContent> content, bool fast, shared_ptr<Log> log)
+AudioDecoder::AudioDecoder (Decoder* parent, shared_ptr<const AudioContent> content, shared_ptr<Log> log)
: _ignore (false)
- , _fast (fast)
+ , _fast (false)
{
BOOST_FOREACH (AudioStreamPtr i, content->streams ()) {
- _streams[i] = shared_ptr<AudioDecoderStream> (new AudioDecoderStream (content, i, parent, fast, log));
+ _streams[i] = shared_ptr<AudioDecoderStream> (new AudioDecoderStream (content, i, parent, log));
}
}
{
_ignore = true;
}
+
+void
+AudioDecoder::set_fast ()
+{
+ for (map<AudioStreamPtr, shared_ptr<AudioDecoderStream> >::const_iterator i = _streams.begin(); i != _streams.end(); ++i) {
+ i->second->set_fast ();
+ }
+}
class AudioDecoder : public boost::enable_shared_from_this<AudioDecoder>
{
public:
- AudioDecoder (Decoder* parent, boost::shared_ptr<const AudioContent>, bool fast, boost::shared_ptr<Log> log);
+ AudioDecoder (Decoder* parent, boost::shared_ptr<const AudioContent>, boost::shared_ptr<Log> log);
/** Try to fetch some audio from a specific place in this content.
* @param frame Frame to start from (after resampling, if applicable)
ContentAudio get (AudioStreamPtr stream, Frame time, Frame length, bool accurate);
void set_ignore ();
-
- bool fast () const {
- return _fast;
- }
+ void set_fast ();
void give (AudioStreamPtr stream, boost::shared_ptr<const AudioBuffers>, ContentTime);
void flush ();
using boost::optional;
using boost::shared_ptr;
-AudioDecoderStream::AudioDecoderStream (shared_ptr<const AudioContent> content, AudioStreamPtr stream, Decoder* decoder, bool fast, shared_ptr<Log> log)
+AudioDecoderStream::AudioDecoderStream (shared_ptr<const AudioContent> content, AudioStreamPtr stream, Decoder* decoder, shared_ptr<Log> log)
: _content (content)
, _stream (stream)
, _decoder (decoder)
, _log (log)
{
if (content->resampled_frame_rate() != _stream->frame_rate() && _stream->channels() > 0) {
- _resampler.reset (new Resampler (_stream->frame_rate(), content->resampled_frame_rate(), _stream->channels (), fast));
+ _resampler.reset (new Resampler (_stream->frame_rate(), content->resampled_frame_rate(), _stream->channels ()));
}
reset_decoded ();
_seek_reference = t;
}
}
+
+void
+AudioDecoderStream::set_fast ()
+{
+ if (_resampler) {
+ _resampler->set_fast ();
+ }
+}
class AudioDecoderStream
{
public:
- AudioDecoderStream (boost::shared_ptr<const AudioContent>, AudioStreamPtr, Decoder* decoder, bool fast, boost::shared_ptr<Log> log);
+ AudioDecoderStream (boost::shared_ptr<const AudioContent>, AudioStreamPtr, Decoder* decoder, boost::shared_ptr<Log> log);
ContentAudio get (Frame time, Frame length, bool accurate);
void audio (boost::shared_ptr<const AudioBuffers>, ContentTime);
void flush ();
void seek (ContentTime time, bool accurate);
+ void set_fast ();
private:
list<DCPTimePeriod> p;
scoped_ptr<DCPDecoder> decoder;
try {
- decoder.reset (new DCPDecoder (shared_from_this(), film()->log(), false));
+ decoder.reset (new DCPDecoder (shared_from_this(), film()->log()));
} catch (...) {
/* Could not load the DCP; guess reels */
list<DCPTimePeriod> p;
bool
DCPContent::can_reference_audio (list<string>& why_not) const
{
- DCPDecoder decoder (shared_from_this(), film()->log(), false);
+ DCPDecoder decoder (shared_from_this(), film()->log());
BOOST_FOREACH (shared_ptr<dcp::Reel> i, decoder.reels()) {
if (!i->main_sound()) {
why_not.push_back (_("The DCP does not have sound in all reels."));
bool
DCPContent::can_reference_subtitle (list<string>& why_not) const
{
- DCPDecoder decoder (shared_from_this(), film()->log(), false);
+ DCPDecoder decoder (shared_from_this(), film()->log());
BOOST_FOREACH (shared_ptr<dcp::Reel> i, decoder.reels()) {
if (!i->main_subtitle()) {
why_not.push_back (_("The DCP does not have subtitles in all reels."));
using boost::shared_ptr;
using boost::dynamic_pointer_cast;
-DCPDecoder::DCPDecoder (shared_ptr<const DCPContent> c, shared_ptr<Log> log, bool fast)
+DCPDecoder::DCPDecoder (shared_ptr<const DCPContent> c, shared_ptr<Log> log)
: _dcp_content (c)
{
video.reset (new VideoDecoder (this, c, log));
- audio.reset (new AudioDecoder (this, c->audio, fast, log));
+ audio.reset (new AudioDecoder (this, c->audio, log));
subtitle.reset (
new SubtitleDecoder (
class DCPDecoder : public Decoder
{
public:
- DCPDecoder (boost::shared_ptr<const DCPContent>, boost::shared_ptr<Log> log, bool fast);
+ DCPDecoder (boost::shared_ptr<const DCPContent>, boost::shared_ptr<Log> log);
std::list<boost::shared_ptr<dcp::Reel> > reels () const {
return _reels;
using boost::dynamic_pointer_cast;
shared_ptr<Decoder>
-decoder_factory (shared_ptr<const Content> content, shared_ptr<Log> log, bool fast)
+decoder_factory (shared_ptr<const Content> content, shared_ptr<Log> log)
{
shared_ptr<const FFmpegContent> fc = dynamic_pointer_cast<const FFmpegContent> (content);
if (fc) {
- return shared_ptr<Decoder> (new FFmpegDecoder (fc, log, fast));
+ return shared_ptr<Decoder> (new FFmpegDecoder (fc, log));
}
shared_ptr<const DCPContent> dc = dynamic_pointer_cast<const DCPContent> (content);
if (dc) {
- return shared_ptr<Decoder> (new DCPDecoder (dc, log, fast));
+ return shared_ptr<Decoder> (new DCPDecoder (dc, log));
}
shared_ptr<const ImageContent> ic = dynamic_pointer_cast<const ImageContent> (content);
extern boost::shared_ptr<Decoder> decoder_factory (
boost::shared_ptr<const Content> content,
- boost::shared_ptr<Log> log,
- bool fast
+ boost::shared_ptr<Log> log
);
using boost::split;
using dcp::Size;
-FFmpegDecoder::FFmpegDecoder (shared_ptr<const FFmpegContent> c, shared_ptr<Log> log, bool fast)
+FFmpegDecoder::FFmpegDecoder (shared_ptr<const FFmpegContent> c, shared_ptr<Log> log)
: FFmpeg (c)
, _log (log)
{
}
if (c->audio) {
- audio.reset (new AudioDecoder (this, c->audio, fast, log));
+ audio.reset (new AudioDecoder (this, c->audio, log));
}
if (c->subtitle) {
class FFmpegDecoder : public FFmpeg, public Decoder
{
public:
- FFmpegDecoder (boost::shared_ptr<const FFmpegContent>, boost::shared_ptr<Log>, bool fast);
+ FFmpegDecoder (boost::shared_ptr<const FFmpegContent>, boost::shared_ptr<Log>);
private:
friend struct ::ffmpeg_pts_offset_test;
continue;
}
- shared_ptr<Decoder> decoder = decoder_factory (i, _film->log(), _fast);
+ shared_ptr<Decoder> decoder = decoder_factory (i, _film->log());
FrameRateChange frc (i->active_video_frame_rate(), _film->video_frame_rate());
if (!decoder) {
decoder->audio->set_ignore ();
}
+ if (decoder->audio && _fast) {
+ decoder->audio->set_fast ();
+ }
+
_pieces.push_back (shared_ptr<Piece> (new Piece (i, decoder, frc)));
}
scoped_ptr<DCPDecoder> decoder;
try {
- decoder.reset (new DCPDecoder (j, _film->log(), false));
+ decoder.reset (new DCPDecoder (j, _film->log()));
} catch (...) {
return a;
}
/** @param in Input sampling rate (Hz)
* @param out Output sampling rate (Hz)
* @param channels Number of channels.
- * @param fast true to be fast rather than good.
*/
-Resampler::Resampler (int in, int out, int channels, bool fast)
+Resampler::Resampler (int in, int out, int channels)
: _in_rate (in)
, _out_rate (out)
, _channels (channels)
{
int error;
- _src = src_new (fast ? SRC_LINEAR : SRC_SINC_BEST_QUALITY, _channels, &error);
+ _src = src_new (SRC_SINC_BEST_QUALITY, _channels, &error);
if (!_src) {
throw runtime_error (String::compose (N_("could not create sample-rate converter (%1)"), error));
}
src_delete (_src);
}
+void
+Resampler::set_fast ()
+{
+ src_delete (_src);
+ int error;
+ _src = src_new (SRC_LINEAR, _channels, &error);
+ if (!_src) {
+ throw runtime_error (String::compose (N_("could not create sample-rate converter (%1)"), error));
+ }
+}
+
shared_ptr<const AudioBuffers>
Resampler::run (shared_ptr<const AudioBuffers> in)
{
class Resampler : public boost::noncopyable
{
public:
- Resampler (int, int, int, bool fast);
+ Resampler (int, int, int);
~Resampler ();
boost::shared_ptr<const AudioBuffers> run (boost::shared_ptr<const AudioBuffers>);
boost::shared_ptr<const AudioBuffers> flush ();
+ void set_fast ();
private:
SRC_STATE* _src;
ContentList c = _parent->selected_subtitle ();
DCPOMATIC_ASSERT (c.size() == 1);
- shared_ptr<Decoder> decoder = decoder_factory (c.front(), _parent->film()->log(), false);
+ shared_ptr<Decoder> decoder = decoder_factory (c.front(), _parent->film()->log());
if (decoder) {
_subtitle_view = new SubtitleView (this, _parent->film(), decoder, c.front()->position ());
: _test_audio_content (content)
, _position (0)
{
- audio.reset (new AudioDecoder (this, content->audio, false, log));
+ audio.reset (new AudioDecoder (this, content->audio, log));
}
bool pass (PassReason, bool)
film->examine_and_add_content (content);
wait_for_jobs ();
- shared_ptr<DCPDecoder> decoder (new DCPDecoder (content, film->log(), false));
+ shared_ptr<DCPDecoder> decoder (new DCPDecoder (content, film->log()));
list<ContentTimePeriod> ctp = decoder->text_subtitles_during (
ContentTimePeriod (
film->examine_and_add_content (content);
wait_for_jobs ();
shared_ptr<Log> log (new NullLog);
- shared_ptr<FFmpegDecoder> decoder (new FFmpegDecoder (content, log, false));
+ shared_ptr<FFmpegDecoder> decoder (new FFmpegDecoder (content, log));
for (vector<int>::const_iterator i = frames.begin(); i != frames.end(); ++i) {
check (decoder, *i);
film->examine_and_add_content (content);
wait_for_jobs ();
shared_ptr<Log> log (new NullLog);
- shared_ptr<FFmpegDecoder> decoder (new FFmpegDecoder (content, log, false));
+ shared_ptr<FFmpegDecoder> decoder (new FFmpegDecoder (content, log));
BOOST_REQUIRE (decoder->video->_content->video_frame_rate());
BOOST_CHECK_CLOSE (decoder->video->_content->video_frame_rate().get(), fps, 0.01);
/* Sound == video so no offset required */
content->_first_video = ContentTime ();
content->ffmpeg_audio_streams().front()->first_audio = ContentTime ();
- FFmpegDecoder decoder (content, film->log(), false);
+ FFmpegDecoder decoder (content, film->log());
BOOST_CHECK_EQUAL (decoder._pts_offset, ContentTime ());
}
/* Common offset should be removed */
content->_first_video = ContentTime::from_seconds (600);
content->ffmpeg_audio_streams().front()->first_audio = ContentTime::from_seconds (600);
- FFmpegDecoder decoder (content, film->log(), false);
+ FFmpegDecoder decoder (content, film->log());
BOOST_CHECK_EQUAL (decoder._pts_offset, ContentTime::from_seconds (-600));
}
/* Video is on a frame boundary */
content->_first_video = ContentTime::from_frames (1, 24);
content->ffmpeg_audio_streams().front()->first_audio = ContentTime ();
- FFmpegDecoder decoder (content, film->log(), false);
+ FFmpegDecoder decoder (content, film->log());
BOOST_CHECK_EQUAL (decoder._pts_offset, ContentTime ());
}
double const frame = 1.0 / 24.0;
content->_first_video = ContentTime::from_seconds (frame + 0.0215);
content->ffmpeg_audio_streams().front()->first_audio = ContentTime ();
- FFmpegDecoder decoder (content, film->log(), false);
+ FFmpegDecoder decoder (content, film->log());
BOOST_CHECK_CLOSE (decoder._pts_offset.seconds(), (frame - 0.0215), 0.00001);
}
double const frame = 1.0 / 24.0;
content->_first_video = ContentTime::from_seconds (frame + 0.0215 + 4.1);
content->ffmpeg_audio_streams().front()->first_audio = ContentTime::from_seconds (4.1);
- FFmpegDecoder decoder (content, film->log(), false);
+ FFmpegDecoder decoder (content, film->log());
BOOST_CHECK_CLOSE (decoder._pts_offset.seconds(), (frame - 0.0215) - 4.1, 0.1);
}
}
static void
resampler_test_one (int from, int to)
{
- Resampler resamp (from, to, 1, false);
+ Resampler resamp (from, to, 1);
/* 3 hours */
int64_t const N = int64_t (from) * 60 * 60 * 3;
Frame const first_frame = video_delay.round_up (content->active_video_frame_rate ()).frames_round (content->active_video_frame_rate ());
- FFmpegDecoder decoder (content, film->log(), false);
+ FFmpegDecoder decoder (content, film->log());
list<ContentVideo> a = decoder.video->get (first_frame, true);
BOOST_CHECK (a.size() == 1);
BOOST_CHECK_EQUAL (a.front().frame.index(), first_frame);