*/
+#include "atmos_decoder.h"
#include "audio_content.h"
+#include "audio_decoder.h"
#include "audio_stream.h"
#include "content.h"
#include "dcp_content.h"
+#include "dcp_decoder.h"
#include "decoder.h"
+#include "decoder_factory.h"
#include "piece.h"
#include "text_content.h"
+#include "text_decoder.h"
#include "video_content.h"
+#include "video_decoder.h"
#include <boost/foreach.hpp>
+#include <boost/ref.hpp>
using std::copy;
using boost::dynamic_pointer_cast;
using boost::optional;
using boost::shared_ptr;
+using boost::weak_ptr;
using namespace dcpomatic;
+Piece::Piece (
+ shared_ptr<const Film> film,
+ ContentList content,
+ bool fast,
+ bool tolerant,
+ bool ignore_video,
+ bool ignore_audio,
+ bool ignore_text,
+ bool play_referenced,
+ optional<int> dcp_decode_reduction
+ )
+ : _content (content)
+ , _done (false)
+{
+ DCPOMATIC_ASSERT (!content.empty());
+
+ /* We assume here that the contents of the list have the required things the same:
+ * - video and audio frame rates
+ * - audio streams and channel counts
+ */
+
+ _frc = FrameRateChange (film, _content.front());
+
+ BOOST_FOREACH (shared_ptr<Content> i, _content)
+ {
+ shared_ptr<Decoder> decoder = decoder_factory (film, i, fast, tolerant, shared_ptr<Decoder>());
+ DCPOMATIC_ASSERT (decoder);
+
+ if (decoder->video && ignore_video) {
+ decoder->video->set_ignore (true);
+ }
+
+ if (decoder->audio && ignore_audio) {
+ decoder->audio->set_ignore (true);
+ }
+
+ if (ignore_text) {
+ BOOST_FOREACH (shared_ptr<TextDecoder> k, decoder->text) {
+ k->set_ignore (true);
+ }
+ }
+
+ shared_ptr<DCPDecoder> dcp = dynamic_pointer_cast<DCPDecoder> (decoder);
+ if (dcp) {
+ dcp->set_decode_referenced (play_referenced);
+ if (play_referenced) {
+ dcp->set_forced_reduction (dcp_decode_reduction);
+ }
+ }
+
+ if (decoder->video) {
+ if (i->video->frame_type() == VIDEO_FRAME_TYPE_3D_LEFT || i->video->frame_type() == VIDEO_FRAME_TYPE_3D_RIGHT) {
+ /* We need a Shuffler to cope with 3D L/R video data arriving out of sequence */
+ /* XXX: move this */
+ //decoder->video->Data.connect (bind(&Shuffler::video, _shuffler, weak_ptr<Piece>(piece), _1));
+ } else {
+ decoder->video->Data.connect (bind(boost::ref(Video), _1));
+ }
+ }
+
+ if (decoder->audio) {
+ decoder->audio->Data.connect (bind(boost::ref(Audio), _1, _2));
+ }
+
+ list<shared_ptr<TextDecoder> >::const_iterator k = decoder->text.begin();
+
+ while (k != decoder->text.end()) {
+ (*k)->BitmapStart.connect (
+ bind(boost::ref(BitmapTextStart), weak_ptr<const TextContent>((*k)->content()), _1)
+ );
+ (*k)->PlainStart.connect (
+ bind(boost::ref(PlainTextStart), weak_ptr<const TextContent>((*k)->content()), _1)
+ );
+ (*k)->Stop.connect (
+ bind(boost::ref(TextStop), weak_ptr<const TextContent>((*k)->content()), _1)
+ );
+
+ ++k;
+ }
+
+ if (decoder->atmos) {
+ decoder->atmos->Data.connect (bind(boost::ref(Atmos), _1));
+ }
+
+ _decoder.push_back (decoder);
+ }
+}
+
+
Piece::Piece (shared_ptr<Content> c, shared_ptr<Decoder> d, FrameRateChange f)
: _frc (f)
, _done (false)
#include "audio_stream.h"
#include "colour_conversion.h"
+#include "content_atmos.h"
+#include "content_audio.h"
+#include "content_text.h"
+#include "content_video.h"
#include "font.h"
#include "dcpomatic_time.h"
#include "frame_rate_change.h"
class Piece
{
public:
+ Piece (
+ boost::shared_ptr<const Film> film,
+ ContentList content,
+ bool fast,
+ bool tolerant,
+ bool ignore_video,
+ bool ignore_audio,
+ bool ignore_text,
+ bool play_referenced,
+ boost::optional<int> dcp_decode_reduction
+ );
+
Piece (boost::shared_ptr<Content> c, boost::shared_ptr<Decoder> d, FrameRateChange f);
void update_pull_to (dcpomatic::DCPTime& pull_to) const;
void add_fonts (std::list<boost::shared_ptr<dcpomatic::Font> >& fonts) const;
+ boost::signals2::signal<void (ContentVideo)> Video;
+ boost::signals2::signal<void (AudioStreamPtr, ContentAudio)> Audio;
+ boost::signals2::signal<void (boost::weak_ptr<const TextContent>, ContentBitmapText)> BitmapTextStart;
+ boost::signals2::signal<void (boost::weak_ptr<const TextContent>, ContentStringText)> PlainTextStart;
+ boost::signals2::signal<void (boost::weak_ptr<const TextContent>, dcpomatic::ContentTime)> TextStop;
+ boost::signals2::signal<void (ContentAtmos)> Atmos;
+
private:
friend struct ::check_reuse_old_data_test;
_shuffler = new Shuffler();
_shuffler->Video.connect(bind(&Player::video, this, _1, _2));
- BOOST_FOREACH (shared_ptr<Content> i, playlist()->content()) {
-
- if (!i->paths_valid ()) {
- continue;
- }
-
- if (_ignore_video && _ignore_audio && i->text.empty()) {
- /* We're only interested in text and this content has none */
- continue;
- }
-
- shared_ptr<Decoder> old_decoder;
- /* XXX: needs to check vector of Content and use the old decoders, but
- * this will all be different as we have to coalesce content before
- * this happens.
- BOOST_FOREACH (shared_ptr<Piece> j, old_pieces) {
- if (j->content == i) {
- old_decoder = j->decoder;
- break;
- }
- }
- */
+ BOOST_FOREACH (ContentList const& i, coalesce(playlist()->content())) {
- shared_ptr<Decoder> decoder = decoder_factory (_film, i, _fast, _tolerant, old_decoder);
- DCPOMATIC_ASSERT (decoder);
-
- FrameRateChange frc (_film, i);
-
- if (decoder->video && _ignore_video) {
- decoder->video->set_ignore (true);
- }
-
- if (decoder->audio && _ignore_audio) {
- decoder->audio->set_ignore (true);
- }
-
- if (_ignore_text) {
- BOOST_FOREACH (shared_ptr<TextDecoder> i, decoder->text) {
- i->set_ignore (true);
- }
- }
-
- shared_ptr<DCPDecoder> dcp = dynamic_pointer_cast<DCPDecoder> (decoder);
- if (dcp) {
- dcp->set_decode_referenced (_play_referenced);
- if (_play_referenced) {
- dcp->set_forced_reduction (_dcp_decode_reduction);
+ bool invalid = false;
+ bool interesting = true;
+ BOOST_FOREACH (shared_ptr<Content> j, i) {
+ if (!j->paths_valid()) {
+ invalid = true;
+ continue;
}
- }
-
- shared_ptr<Piece> piece (new Piece (i, decoder, frc));
- _pieces.push_back (piece);
-
- if (decoder->video) {
- if (i->video->frame_type() == VIDEO_FRAME_TYPE_3D_LEFT || i->video->frame_type() == VIDEO_FRAME_TYPE_3D_RIGHT) {
- /* We need a Shuffler to cope with 3D L/R video data arriving out of sequence */
- decoder->video->Data.connect (bind (&Shuffler::video, _shuffler, weak_ptr<Piece>(piece), _1));
- } else {
- decoder->video->Data.connect (bind (&Player::video, this, weak_ptr<Piece>(piece), _1));
+ if (_ignore_video && _ignore_audio && j->text.empty()) {
+ /* We're only interested in text and this content has none */
+ interesting = false;
+ continue;
}
}
- if (decoder->audio) {
- decoder->audio->Data.connect (bind (&Player::audio, this, weak_ptr<Piece> (piece), _1, _2));
+ if (invalid || !interesting) {
+ continue;
}
- list<shared_ptr<TextDecoder> >::const_iterator j = decoder->text.begin();
-
- while (j != decoder->text.end()) {
- (*j)->BitmapStart.connect (
- bind(&Player::bitmap_text_start, this, weak_ptr<Piece>(piece), weak_ptr<const TextContent>((*j)->content()), _1)
- );
- (*j)->PlainStart.connect (
- bind(&Player::plain_text_start, this, weak_ptr<Piece>(piece), weak_ptr<const TextContent>((*j)->content()), _1)
- );
- (*j)->Stop.connect (
- bind(&Player::subtitle_stop, this, weak_ptr<Piece>(piece), weak_ptr<const TextContent>((*j)->content()), _1)
- );
+ shared_ptr<Piece> piece(
+ new Piece(
+ _film,
+ i,
+ _fast,
+ _tolerant,
+ _ignore_video,
+ _ignore_audio,
+ _ignore_text,
+ _play_referenced,
+ _dcp_decode_reduction
+ ));
+
+ piece->Video.connect (bind(&Player::video, this, weak_ptr<Piece>(piece), _1));
+ piece->Audio.connect (bind(&Player::audio, this, weak_ptr<Piece>(piece), _1, _2));
+ piece->BitmapTextStart.connect (bind(&Player::bitmap_text_start, this, weak_ptr<Piece>(piece), _1, _2));
+ piece->PlainTextStart.connect (bind(&Player::plain_text_start, this, weak_ptr<Piece>(piece), _1, _2));
+ piece->TextStop.connect (bind(&Player::text_stop, this, weak_ptr<Piece>(piece), _1, _2));
+ piece->Atmos.connect (bind(&Player::atmos, this, weak_ptr<Piece>(piece), _1));
- ++j;
- }
+ _pieces.push_back (piece);
- if (decoder->atmos) {
- decoder->atmos->Data.connect (bind(&Player::atmos, this, weak_ptr<Piece>(piece), _1));
- }
+ /* XXX: needs to check vector of Content and use the old decoders, but
+ * this will all be different as we have to coalesce content before
+ * this happens.
+ BOOST_FOREACH (shared_ptr<Piece> j, old_pieces) {
+ if (j->content == i) {
+ old_decoder = j->decoder;
+ break;
+ }
+ }
+ */
+
+#if 0
+ XXX
+ if (j->video->frame_type() == VIDEO_FRAME_TYPE_3D_LEFT || j->video->frame_type() == VIDEO_FRAME_TYPE_3D_RIGHT) {
+ /* We need a Shuffler to cope with 3D L/R video data arriving out of sequence */
+ decoder->video->Data.connect (bind(&Shuffler::video, _shuffler, weak_ptr<Piece>(piece), _1));
+#endif
}
_black = Empty (_film, playlist(), bind(&have_video, _1), _playback_length);
}
void
-Player::subtitle_stop (weak_ptr<Piece> wp, weak_ptr<const TextContent> wc, ContentTime to)
+Player::text_stop (weak_ptr<Piece> wp, weak_ptr<const TextContent> wc, ContentTime to)
{
shared_ptr<const TextContent> text = wc.lock ();
if (!text) {
Atmos (data.data, DCPTime::from_frames(data.frame, _film->video_frame_rate()), data.metadata);
}
+
+vector<ContentList>
+Player::coalesce (ContentList const& content) const
+{
+ vector<ContentList> coalesced;
+ BOOST_FOREACH (shared_ptr<Content> i, content) {
+ ContentList group;
+ group.push_back (i);
+ coalesced.push_back (group);
+ }
+
+ return coalesced;
+}
+