using boost::shared_ptr;
AudioDecoder::AudioDecoder (Decoder* parent, shared_ptr<const AudioContent> content, shared_ptr<Log> log)
- : _ignore (false)
+ : DecoderPart (parent)
{
BOOST_FOREACH (AudioStreamPtr i, content->streams ()) {
- _streams[i] = shared_ptr<AudioDecoderStream> (new AudioDecoderStream (content, i, parent, log));
+ _streams[i] = shared_ptr<AudioDecoderStream> (new AudioDecoderStream (content, i, parent, this, log));
}
}
void
AudioDecoder::give (AudioStreamPtr stream, shared_ptr<const AudioBuffers> data, ContentTime time)
{
- if (_ignore) {
+ if (ignore ()) {
return;
}
}
}
-/** Set this decoder never to produce any data */
-void
-AudioDecoder::set_ignore ()
-{
- _ignore = true;
-}
-
void
AudioDecoder::set_fast ()
{
#include "decoder.h"
#include "content_audio.h"
#include "audio_stream.h"
+#include "decoder_part.h"
#include <boost/enable_shared_from_this.hpp>
class AudioBuffers;
/** @class AudioDecoder.
* @brief Parent class for audio decoders.
*/
-class AudioDecoder : public boost::enable_shared_from_this<AudioDecoder>
+class AudioDecoder : public boost::enable_shared_from_this<AudioDecoder>, public DecoderPart
{
public:
AudioDecoder (Decoder* parent, boost::shared_ptr<const AudioContent>, boost::shared_ptr<Log> log);
*/
ContentAudio get (AudioStreamPtr stream, Frame time, Frame length, bool accurate);
- void set_ignore ();
void set_fast ();
void give (AudioStreamPtr stream, boost::shared_ptr<const AudioBuffers>, ContentTime);
private:
/** An AudioDecoderStream object to manage each stream in _audio_content */
std::map<AudioStreamPtr, boost::shared_ptr<AudioDecoderStream> > _streams;
- bool _ignore;
};
#endif
using boost::optional;
using boost::shared_ptr;
-AudioDecoderStream::AudioDecoderStream (shared_ptr<const AudioContent> content, AudioStreamPtr stream, Decoder* decoder, shared_ptr<Log> log)
+AudioDecoderStream::AudioDecoderStream (
+ shared_ptr<const AudioContent> content, AudioStreamPtr stream, Decoder* decoder, AudioDecoder* audio_decoder, shared_ptr<Log> log
+ )
: _content (content)
, _stream (stream)
, _decoder (decoder)
+ , _audio_decoder (audio_decoder)
, _log (log)
/* We effectively start having done a seek to zero; this allows silence-padding of the first
data that comes out of our decoder.
}
if (missing) {
- _decoder->maybe_seek_audio (ContentTime::from_frames (*missing, _content->resampled_frame_rate()), accurate);
+ _audio_decoder->maybe_seek (ContentTime::from_frames (*missing, _content->resampled_frame_rate()), accurate);
}
/* Offset of the data that we want from the start of _decoded.audio
class AudioDecoderStream
{
public:
- AudioDecoderStream (boost::shared_ptr<const AudioContent>, AudioStreamPtr, Decoder* decoder, boost::shared_ptr<Log> log);
+ AudioDecoderStream (boost::shared_ptr<const AudioContent>, AudioStreamPtr, Decoder* decoder, AudioDecoder* audio_decoder, boost::shared_ptr<Log> log);
ContentAudio get (Frame time, Frame length, bool accurate);
void audio (boost::shared_ptr<const AudioBuffers>, ContentTime);
boost::shared_ptr<const AudioContent> _content;
AudioStreamPtr _stream;
Decoder* _decoder;
+ AudioDecoder* _audio_decoder;
boost::shared_ptr<Log> _log;
boost::shared_ptr<Resampler> _resampler;
boost::optional<Frame> _position;
}
}
- _video_position = _audio_position = _subtitle_position = _next;
+ video->set_position (_next);
+ audio->set_position (_next);
+ subtitle->set_position (_next);
_next += ContentTime::from_frames (1, vfr);
if ((*_reel)->main_picture ()) {
}
subtitle->give_text (p, s);
- _subtitle_position = p.from;
+ subtitle->set_position (p.from);
return false;
}
position.reset ();
seek (time, accurate);
}
-
-void
-Decoder::maybe_seek_video (ContentTime time, bool accurate)
-{
- maybe_seek (_video_position, time, accurate);
-}
-
-void
-Decoder::maybe_seek_audio (ContentTime time, bool accurate)
-{
- maybe_seek (_audio_position, time, accurate);
-}
-
-void
-Decoder::maybe_seek_subtitle (ContentTime time, bool accurate)
-{
- maybe_seek (_subtitle_position, time, accurate);
-}
PASS_REASON_SUBTITLE
};
- void maybe_seek_video (ContentTime time, bool accurate);
- void maybe_seek_audio (ContentTime time, bool accurate);
- void maybe_seek_subtitle (ContentTime time, bool accurate);
-
/** @return true if this decoder has already returned all its data and will give no more */
virtual bool pass (PassReason, bool accurate) = 0;
*/
virtual void reset () {}
-protected:
- boost::optional<ContentTime> _video_position;
- boost::optional<ContentTime> _audio_position;
- boost::optional<ContentTime> _subtitle_position;
+ void maybe_seek (boost::optional<ContentTime>& position, ContentTime time, bool accurate);
private:
/** Seek so that the next pass() will yield the next thing
* it may seek to just the right spot.
*/
virtual void seek (ContentTime time, bool accurate) = 0;
- void maybe_seek (boost::optional<ContentTime>& position, ContentTime time, bool accurate);
};
#endif
--- /dev/null
+/*
+ Copyright (C) 2012-2016 Carl Hetherington <cth@carlh.net>
+
+ This file is part of DCP-o-matic.
+
+ DCP-o-matic is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ DCP-o-matic is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with DCP-o-matic. If not, see <http://www.gnu.org/licenses/>.
+
+*/
+
+#include "decoder_part.h"
+#include "decoder.h"
+
+DecoderPart::DecoderPart (Decoder* parent)
+ : _parent (parent)
+ , _ignore (false)
+{
+
+}
+
+void
+DecoderPart::maybe_seek (ContentTime time, bool accurate)
+{
+ _parent->maybe_seek (_position, time, accurate);
+}
--- /dev/null
+/*
+ Copyright (C) 2012-2016 Carl Hetherington <cth@carlh.net>
+
+ This file is part of DCP-o-matic.
+
+ DCP-o-matic is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ DCP-o-matic is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with DCP-o-matic. If not, see <http://www.gnu.org/licenses/>.
+
+*/
+
+#ifndef DCPOMATIC_DECODER_PART_H
+#define DCPOMATIC_DECODER_PART_H
+
+#include "dcpomatic_time.h"
+#include <boost/optional.hpp>
+
+class Decoder;
+
+class DecoderPart
+{
+public:
+ DecoderPart (Decoder* parent);
+
+ void set_ignore () {
+ _ignore = true;
+ }
+
+ bool ignore () const {
+ return _ignore;
+ }
+
+ void set_position (ContentTime position) {
+ _position = position;
+ }
+
+ boost::optional<ContentTime> position () const {
+ return _position;
+ }
+
+ void maybe_seek (ContentTime time, bool accurate);
+
+protected:
+ Decoder* _parent;
+
+private:
+ bool _ignore;
+ boost::optional<ContentTime> _position;
+};
+
+#endif
LOG_WARNING ("Crazy timestamp %s", to_string (ct));
}
- update_position (_audio_position, ct);
+ audio->set_position (ct);
/* Give this data provided there is some, and its time is sane */
if (ct >= ContentTime() && data->frames() > 0) {
shared_ptr<ImageProxy> (new RawImageProxy (image)),
llrint (pts * _ffmpeg_content->active_video_frame_rate ())
);
- update_position (_video_position, ContentTime::from_seconds (pts));
+ video->set_position (ContentTime::from_seconds (pts));
} else {
LOG_WARNING_NC ("Dropping frame without PTS");
}
FFmpegSubtitlePeriod sub_period = subtitle_period (sub);
ContentTimePeriod period;
period.from = sub_period.from + _pts_offset;
- update_position (_subtitle_position, period.from);
+ subtitle->set_position (period.from);
if (sub_period.to) {
/* We already know the subtitle period `to' time */
period.to = sub_period.to.get() + _pts_offset;
subtitle->give_text (period, i);
}
}
-
-void
-FFmpegDecoder::update_position (optional<ContentTime>& current, ContentTime p)
-{
- /* current should err on the side of being too big, as then there is less
- chance that we will erroneously decide not to seek when current > request.
- */
- if (!current) {
- current = p;
- } else {
- current = max (*current, p);
- }
-}
bool pass (PassReason, bool accurate);
void seek (ContentTime time, bool);
void flush ();
- void update_position (boost::optional<ContentTime>& current, ContentTime p);
AVSampleFormat audio_sample_format (boost::shared_ptr<FFmpegAudioStream> stream) const;
int bytes_per_audio_sample (boost::shared_ptr<FFmpegAudioStream> stream) const;
}
}
- _video_position = ContentTime::from_frames (_frame_video_position, _image_content->active_video_frame_rate ());
+ video->set_position (ContentTime::from_frames (_frame_video_position, _image_content->active_video_frame_rate ()));
video->give (_image, _frame_video_position);
++_frame_video_position;
return false;
function<list<ContentTimePeriod> (ContentTimePeriod, bool)> image_during,
function<list<ContentTimePeriod> (ContentTimePeriod, bool)> text_during
)
- : _parent (parent)
+ : DecoderPart (parent)
, _content (c)
, _image_during (image_during)
, _text_during (text_during)
/* Suggest to our parent decoder that it might want to seek if we haven't got what we're being asked for */
if (missing) {
- _parent->maybe_seek_subtitle (*missing, true);
+ maybe_seek (*missing, true);
}
/* Now enough pass() calls will either:
#include "rect.h"
#include "types.h"
#include "content_subtitle.h"
+#include "decoder_part.h"
#include <dcp/subtitle_string.h>
namespace sub {
class Image;
-class SubtitleDecoder
+class SubtitleDecoder : public DecoderPart
{
public:
/** Second parameter to the _during functions is true if we
private:
- Decoder* _parent;
std::list<ContentImageSubtitle> _decoded_image;
std::list<ContentTextSubtitle> _decoded_text;
boost::shared_ptr<const SubtitleContent> _content;
ContentTimePeriod const p = content_time_period (_subtitles[_next]);
subtitle->give_text (p, _subtitles[_next]);
- _subtitle_position = p.from;
+ subtitle->set_position (p.from);
++_next;
return false;
using boost::optional;
VideoDecoder::VideoDecoder (Decoder* parent, shared_ptr<const Content> c, shared_ptr<Log> log)
+ : DecoderPart (parent)
#ifdef DCPOMATIC_DEBUG
- : test_gaps (0)
- , _parent (parent),
- _content (c)
-#else
- : _parent (parent)
- , _content (c)
+ , test_gaps (0)
#endif
+ , _content (c)
, _log (log)
, _last_seek_accurate (true)
- , _ignore (false)
{
_black_image.reset (new Image (AV_PIX_FMT_RGB24, _content->video->size(), true));
_black_image->make_black ();
*/
seek_frame *= 2;
}
- _parent->maybe_seek_video (ContentTime::from_frames (seek_frame, _content->active_video_frame_rate()), accurate);
+ maybe_seek (ContentTime::from_frames (seek_frame, _content->active_video_frame_rate()), accurate);
}
/* Work out the number of frames that we should return; we
void
VideoDecoder::give (shared_ptr<const ImageProxy> image, Frame frame)
{
- if (_ignore) {
+ if (ignore ()) {
return;
}
_last_seek_time = s;
_last_seek_accurate = accurate;
}
-
-/** Set this decoder never to produce any data */
-void
-VideoDecoder::set_ignore ()
-{
- _ignore = true;
-}
#include "video_content.h"
#include "util.h"
#include "content_video.h"
+#include "decoder_part.h"
#include <boost/signals2.hpp>
#include <boost/shared_ptr.hpp>
/** @class VideoDecoder
* @brief Parent for classes which decode video.
*/
-class VideoDecoder
+class VideoDecoder : public DecoderPart
{
public:
VideoDecoder (Decoder* parent, boost::shared_ptr<const Content> c, boost::shared_ptr<Log> log);
std::list<ContentVideo> get (Frame frame, bool accurate);
- void set_ignore ();
- bool ignore () const {
- return _ignore;
- }
-
#ifdef DCPOMATIC_DEBUG
int test_gaps;
#endif
void fill_one_eye (Frame from, Frame to, Eyes);
void fill_both_eyes (VideoFrame from, VideoFrame to);
- Decoder* _parent;
boost::shared_ptr<const Content> _content;
boost::shared_ptr<Log> _log;
std::list<ContentVideo> _decoded;
boost::shared_ptr<Image> _black_image;
boost::optional<ContentTime> _last_seek_time;
bool _last_seek_accurate;
- /** true if this decoder should ignore all video; i.e. never produce any */
- bool _ignore;
/** if set, this is a frame for which we got no data because the Decoder said
* it has no more to give.
*/
);
}
- _video_position = _next;
+ video->set_position (_next);
_next += ContentTime::from_frames (1, vfr);
return false;
}
dcpomatic_time.cc
decoder.cc
decoder_factory.cc
+ decoder_part.cc
digester.cc
dolby_cp750.cc
emailer.cc