using std::cout;
using std::map;
using boost::shared_ptr;
+using boost::optional;
AudioDecoder::AudioDecoder (Decoder* parent, shared_ptr<const AudioContent> content, shared_ptr<Log> log)
: DecoderPart (parent, log)
void
AudioDecoder::flush ()
{
- for (map<AudioStreamPtr, shared_ptr<AudioDecoderStream> >::const_iterator i = _streams.begin(); i != _streams.end(); ++i) {
+ for (StreamMap::const_iterator i = _streams.begin(); i != _streams.end(); ++i) {
i->second->flush ();
}
}
AudioDecoder::seek (ContentTime t, bool accurate)
{
_log->log (String::compose ("AD seek to %1", to_string(t)), LogEntry::TYPE_DEBUG_DECODE);
- for (map<AudioStreamPtr, shared_ptr<AudioDecoderStream> >::const_iterator i = _streams.begin(); i != _streams.end(); ++i) {
+ for (StreamMap::const_iterator i = _streams.begin(); i != _streams.end(); ++i) {
i->second->seek (t, accurate);
}
}
void
AudioDecoder::set_fast ()
{
- for (map<AudioStreamPtr, shared_ptr<AudioDecoderStream> >::const_iterator i = _streams.begin(); i != _streams.end(); ++i) {
+ for (StreamMap::const_iterator i = _streams.begin(); i != _streams.end(); ++i) {
i->second->set_fast ();
}
}
+
+optional<ContentTime>
+AudioDecoder::position () const
+{
+ optional<ContentTime> pos;
+ for (StreamMap::const_iterator i = _streams.begin(); i != _streams.end(); ++i) {
+ if (!pos || (i->second->position() && i->second->position().get() < pos.get())) {
+ pos = i->second->position();
+ }
+ }
+ return pos;
+}
void flush ();
void seek (ContentTime t, bool accurate);
+ boost::optional<ContentTime> position () const;
+
private:
/** An AudioDecoderStream object to manage each stream in _audio_content */
- std::map<AudioStreamPtr, boost::shared_ptr<AudioDecoderStream> > _streams;
+ typedef std::map<AudioStreamPtr, boost::shared_ptr<AudioDecoderStream> > StreamMap;
+ StreamMap _streams;
};
#endif
_resampler->set_fast ();
}
}
+
+optional<ContentTime>
+AudioDecoderStream::position () const
+{
+ if (!_position) {
+ return optional<ContentTime> ();
+ }
+
+ return ContentTime::from_frames (_position.get(), _content->resampled_frame_rate());
+}
void seek (ContentTime time, bool accurate);
void set_fast ();
+ boost::optional<ContentTime> position () const;
+
private:
void reset_decoded ();
}
}
- 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->set_position (p.from);
return false;
}
*/
#include "decoder.h"
+#include "decoder_part.h"
#include <iostream>
using std::cout;
using boost::optional;
void
-Decoder::maybe_seek (optional<ContentTime>& position, ContentTime time, bool accurate)
+Decoder::maybe_seek (opional<ContentTime> position, ContentTime time, bool accurate)
{
- if (position && (time >= *position && time < (*position + ContentTime::from_seconds(1)))) {
+ if (position && (time >= position.get() && time < (position.get() + ContentTime::from_seconds(1)))) {
/* No need to seek: caller should just pass() */
return;
}
- position.reset ();
seek (time, accurate);
}
class VideoDecoder;
class AudioDecoder;
class SubtitleDecoder;
+class DecoderPart;
/** @class Decoder.
* @brief Parent class for decoders of content.
*/
virtual void reset () {}
- void maybe_seek (boost::optional<ContentTime>& position, ContentTime time, bool accurate);
+ void maybe_seek (boost::optional<ContentTime> position, ContentTime time, bool accurate);
private:
/** Seek so that the next pass() will yield the next thing
void
DecoderPart::maybe_seek (ContentTime time, bool accurate)
{
- _parent->maybe_seek (_position, time, accurate);
+ _parent->maybe_seek (position(), time, accurate);
}
return _ignore;
}
- void set_position (ContentTime position) {
- _position = position;
- }
-
- boost::optional<ContentTime> position () const {
- return _position;
- }
+ virtual boost::optional<ContentTime> position () const = 0;
void maybe_seek (ContentTime time, bool accurate);
private:
bool _ignore;
- boost::optional<ContentTime> _position;
};
#endif
LOG_WARNING ("Crazy timestamp %1", to_string (ct));
}
- audio->set_position (ct);
-
/* Give this data provided there is some, and its time is sane */
if (ct >= ContentTime() && data->frames() > 0) {
audio->give (*stream, data, ct);
shared_ptr<ImageProxy> (new RawImageProxy (image)),
llrint (pts * _ffmpeg_content->active_video_frame_rate ())
);
- 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;
- subtitle->set_position (period.from);
/* We can't trust the `to' time from sub_period as there are some decoders which
give a sub_period time for `to' which is subsequently overridden by a `stop' subtitle;
see also FFmpegExaminer.
}
}
- 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;
SubtitleDecoder::give_image (ContentTimePeriod period, shared_ptr<Image> image, dcpomatic::Rect<double> rect)
{
_decoded_image.push_back (ContentImageSubtitle (period, image, rect));
+ _position = period.from;
}
void
}
_decoded_text.push_back (ContentTextSubtitle (period, s));
+ _position = period.from;
}
/** Get the subtitles that correspond to a given list of periods.
{
_log->log (String::compose ("SD seek to %1", to_string(t)), LogEntry::TYPE_DEBUG_DECODE);
reset ();
+ _position.reset ();
}
void
return _content;
}
+ boost::optional<ContentTime> position () const {
+ return _position;
+ }
+
+ void reset_position () {
+ _position.reset ();
+ }
+
private:
std::list<ContentImageSubtitle> _decoded_image;
boost::function<std::list<ContentTimePeriod> (ContentTimePeriod, bool)> _image_during;
boost::function<std::list<ContentTimePeriod> (ContentTimePeriod, bool)> _text_during;
+
+ boost::optional<ContentTime> _position;
};
#endif
ContentTimePeriod const p = content_time_period (_subtitles[_next]);
subtitle->give_text (p, _subtitles[_next]);
- subtitle->set_position (p.from);
++_next;
return false;
}
_log->log (String::compose ("VD receives %1", frame), LogEntry::TYPE_DEBUG_DECODE);
+ _position = ContentTime::from_frames (frame, _content->active_video_frame_rate());
/* Work out what we are going to push into _decoded next */
list<ContentVideo> to_push;
_decoded.clear ();
_last_seek_time = s;
_last_seek_accurate = accurate;
+ _position.reset ();
}
void seek (ContentTime time, bool accurate);
void give (boost::shared_ptr<const ImageProxy>, Frame frame);
+ boost::optional<ContentTime> position () const {
+ return _position;
+ }
+
+ void reset_position () {
+ _position.reset ();
+ }
+
private:
std::list<ContentVideo> decoded (Frame frame);
* it has no more to give.
*/
boost::optional<Frame> _no_data_frame;
+ boost::optional<ContentTime> _position;
};
#endif
);
}
- video->set_position (_next);
_next += ContentTime::from_frames (1, vfr);
return false;
}