wip: allow multi-content pieces. 1771-resample-glitches-take3
authorCarl Hetherington <cth@carlh.net>
Thu, 25 Jun 2020 07:55:19 +0000 (09:55 +0200)
committerCarl Hetherington <cth@carlh.net>
Tue, 1 Dec 2020 15:43:36 +0000 (16:43 +0100)
src/lib/piece.cc
src/lib/piece.h
src/lib/player.cc
src/lib/player.h

index 03a92be6c3c0dc794942b02c640b95d1005828e9..55ee7d151e8295618b4c48c78d23f63665e768c7 100644 (file)
 */
 
 
+#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;
@@ -36,9 +43,99 @@ using std::map;
 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)
index c07fca20ee0515d0bab6640aa1259bbc243ac413..60adb23e7d7a13684a88b3d103ed627daa153862 100644 (file)
 
 #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"
@@ -38,6 +42,18 @@ struct check_reuse_old_data_test;
 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;
@@ -73,6 +89,13 @@ public:
 
        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;
 
index 7e96144bb82ede4e5c5e2e8be1880935d9b95cd6..f076678f051463e0a46eac9d255ecce1a27cc1e5 100644 (file)
@@ -177,91 +177,65 @@ Player::setup_pieces_unlocked ()
        _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);
@@ -988,7 +962,7 @@ Player::plain_text_start (weak_ptr<Piece> wp, weak_ptr<const TextContent> wc, Co
 }
 
 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) {
@@ -1209,3 +1183,17 @@ Player::atmos (weak_ptr<Piece>, ContentAtmos data)
        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;
+}
+
index eb1b4ea3607b199ead73e0cbbf9b775e96ca7700..2ae1628c30b6e842650927e3c69e88201fda8510 100644 (file)
@@ -122,6 +122,7 @@ private:
        void construct ();
        void setup_pieces ();
        void setup_pieces_unlocked ();
+       std::vector<ContentList> coalesce (ContentList const& content) const;
        void flush ();
        void film_change (ChangeType, Film::Property);
        void playlist_change (ChangeType);
@@ -132,7 +133,7 @@ private:
        void audio (boost::weak_ptr<Piece>, AudioStreamPtr, ContentAudio);
        void bitmap_text_start (boost::weak_ptr<Piece>, boost::weak_ptr<const TextContent>, ContentBitmapText);
        void plain_text_start (boost::weak_ptr<Piece>, boost::weak_ptr<const TextContent>, ContentStringText);
-       void subtitle_stop (boost::weak_ptr<Piece>, boost::weak_ptr<const TextContent>, dcpomatic::ContentTime);
+       void text_stop (boost::weak_ptr<Piece>, boost::weak_ptr<const TextContent>, dcpomatic::ContentTime);
        void atmos (boost::weak_ptr<Piece>, ContentAtmos);
 
        dcpomatic::DCPTime one_video_frame () const;