Basics of Atmos content support; can be added to project and appears in timeline.
authorCarl Hetherington <cth@carlh.net>
Wed, 25 May 2016 15:55:42 +0000 (16:55 +0100)
committerCarl Hetherington <cth@carlh.net>
Wed, 25 May 2016 15:55:42 +0000 (16:55 +0100)
src/lib/atmos_mxf_content.cc [new file with mode: 0644]
src/lib/atmos_mxf_content.h [new file with mode: 0644]
src/lib/content_factory.cc
src/lib/player.cc
src/lib/wscript
src/wx/timeline.cc
src/wx/timeline_atmos_content_view.cc [new file with mode: 0644]
src/wx/timeline_atmos_content_view.h [new file with mode: 0644]
src/wx/timeline_labels_view.cc
src/wx/timeline_labels_view.h
src/wx/wscript

diff --git a/src/lib/atmos_mxf_content.cc b/src/lib/atmos_mxf_content.cc
new file mode 100644 (file)
index 0000000..927d36f
--- /dev/null
@@ -0,0 +1,92 @@
+/*
+    Copyright (C) 2016 Carl Hetherington <cth@carlh.net>
+
+    This program 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.
+
+    This program 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 this program; if not, write to the Free Software
+    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+*/
+
+#include "atmos_mxf_content.h"
+#include "job.h"
+#include "film.h"
+#include "compose.hpp"
+#include <dcp/atmos_asset.h>
+#include <dcp/exceptions.h>
+#include <libxml++/libxml++.h>
+
+#include "i18n.h"
+
+using std::list;
+using std::string;
+using boost::shared_ptr;
+
+AtmosMXFContent::AtmosMXFContent (shared_ptr<const Film> film, boost::filesystem::path path)
+       : Content (film, path)
+{
+
+}
+
+AtmosMXFContent::AtmosMXFContent (shared_ptr<const Film> film, cxml::ConstNodePtr node, int)
+       : Content (film, node)
+{
+
+}
+
+bool
+AtmosMXFContent::valid_mxf (boost::filesystem::path path)
+{
+       try {
+               shared_ptr<dcp::AtmosAsset> a (new dcp::AtmosAsset (path));
+               return true;
+       } catch (dcp::MXFFileError& e) {
+
+       } catch (dcp::DCPReadError& e) {
+
+       }
+
+       return false;
+}
+
+void
+AtmosMXFContent::examine (shared_ptr<Job> job)
+{
+       job->set_progress_unknown ();
+       Content::examine (job);
+       shared_ptr<dcp::AtmosAsset> a (new dcp::AtmosAsset (path(0)));
+
+       {
+               boost::mutex::scoped_lock lm (_mutex);
+               _length = a->intrinsic_duration ();
+       }
+}
+
+string
+AtmosMXFContent::summary () const
+{
+       return String::compose (_("%1 [Atmos]"), path_summary());
+}
+
+void
+AtmosMXFContent::as_xml (xmlpp::Node* node) const
+{
+       node->add_child("Type")->add_child_text ("AtmosMXF");
+       Content::as_xml (node);
+}
+
+DCPTime
+AtmosMXFContent::full_length () const
+{
+       FrameRateChange const frc (active_video_frame_rate(), film()->video_frame_rate());
+       return DCPTime::from_frames (llrint (_length * frc.factor()), film()->video_frame_rate());
+}
diff --git a/src/lib/atmos_mxf_content.h b/src/lib/atmos_mxf_content.h
new file mode 100644 (file)
index 0000000..b030948
--- /dev/null
@@ -0,0 +1,41 @@
+/*
+    Copyright (C) 2016 Carl Hetherington <cth@carlh.net>
+
+    This program 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.
+
+    This program 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 this program; if not, write to the Free Software
+    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+*/
+
+#include "content.h"
+
+class AtmosMXFContent : public Content
+{
+public:
+       AtmosMXFContent (boost::shared_ptr<const Film> film, boost::filesystem::path path);
+       AtmosMXFContent (boost::shared_ptr<const Film> film, cxml::ConstNodePtr node, int version);
+
+       boost::shared_ptr<AtmosMXFContent> shared_from_this () {
+               return boost::dynamic_pointer_cast<AtmosMXFContent> (Content::shared_from_this ());
+       }
+
+       void examine (boost::shared_ptr<Job> job);
+       std::string summary () const;
+       void as_xml (xmlpp::Node* node) const;
+       DCPTime full_length () const;
+
+       static bool valid_mxf (boost::filesystem::path path);
+
+private:
+       Frame _length;
+};
index 706c7975403b9110d10e1c834a325216d6b18667..df803809f537565af2afb319e8b312c4bccc3495 100644 (file)
@@ -24,6 +24,7 @@
 #include "ffmpeg_content.h"
 #include "audio_content.h"
 #include "image_content.h"
+#include "atmos_mxf_content.h"
 #include "text_subtitle_content.h"
 #include "dcp_content.h"
 #include "dcp_subtitle_content.h"
@@ -90,6 +91,8 @@ content_factory (shared_ptr<const Film> film, cxml::NodePtr node, int version, l
                content.reset (new DCPSubtitleContent (film, node, version));
        } else if (type == "VideoMXF") {
                content.reset (new VideoMXFContent (film, node, version));
+       } else if (type == "AtmosMXF") {
+               content.reset (new AtmosMXFContent (film, node, version));
        }
 
        return content;
@@ -167,6 +170,8 @@ content_factory (shared_ptr<const Film> film, boost::filesystem::path path)
                        content.reset (new DCPSubtitleContent (film, path));
                } else if (ext == ".mxf" && VideoMXFContent::valid_mxf (path)) {
                        content.reset (new VideoMXFContent (film, path));
+               } else if (ext == ".mxf" && AtmosMXFContent::valid_mxf (path)) {
+                       content.reset (new AtmosMXFContent (film, path));
                }
 
                if (!content) {
index 0c513056c56e45ddc1e301d001da346862de7401..6d155836fbd47f4055cdbf4832883c1392ec7f2a 100644 (file)
@@ -188,7 +188,10 @@ Player::setup_pieces ()
                        frc = FrameRateChange (vmc->active_video_frame_rate(), _film->video_frame_rate());
                }
 
-               DCPOMATIC_ASSERT (decoder);
+               if (!decoder) {
+                       /* Not something that we can decode; e.g. Atmos content */
+                       continue;
+               }
 
                if (decoder->video && _ignore_video) {
                        decoder->video->set_ignore ();
index 727a398af146bc19a7b0ddedc96580a215b8e8fb..4c5ed04db998ad2859604d4f688e8f9e6eb8849b 100644 (file)
@@ -21,6 +21,7 @@ import i18n
 
 sources = """
           analyse_audio_job.cc
+          atmos_mxf_content.cc
           audio_analysis.cc
           audio_buffers.cc
           audio_content.cc
index 8ce811c28c3f668ea913008e16ce4c09fd631a21..2a0f96f05d1eedcbc3e7b09ebf20ead7f4328a0f 100644 (file)
@@ -25,6 +25,7 @@
 #include "timeline_video_content_view.h"
 #include "timeline_audio_content_view.h"
 #include "timeline_subtitle_content_view.h"
+#include "timeline_atmos_content_view.h"
 #include "content_panel.h"
 #include "wx_util.h"
 #include "lib/film.h"
@@ -34,6 +35,7 @@
 #include "lib/audio_content.h"
 #include "lib/subtitle_content.h"
 #include "lib/video_content.h"
+#include "lib/atmos_mxf_content.h"
 #include <wx/graphics.h>
 #include <boost/weak_ptr.hpp>
 #include <boost/foreach.hpp>
@@ -157,6 +159,10 @@ Timeline::recreate_views ()
                if (i->subtitle) {
                        _views.push_back (shared_ptr<TimelineView> (new TimelineSubtitleContentView (*this, i)));
                }
+
+               if (dynamic_pointer_cast<AtmosMXFContent> (i)) {
+                       _views.push_back (shared_ptr<TimelineView> (new TimelineAtmosContentView (*this, i)));
+               }
        }
 
        assign_tracks ();
@@ -187,6 +193,36 @@ Timeline::assign_tracks ()
                }
        }
 
+       /* See if we have any subtitle / atmos / right-eye views */
+       bool have_3d = false;
+       bool have_subtitle = false;
+       bool have_atmos = false;
+       BOOST_FOREACH (shared_ptr<TimelineView> i, _views) {
+               shared_ptr<TimelineContentView> cv = dynamic_pointer_cast<TimelineContentView> (i);
+               if (!cv) {
+                       continue;
+               }
+
+               if (dynamic_pointer_cast<TimelineVideoContentView> (i)) {
+                       if (cv->content()->video->frame_type() == VIDEO_FRAME_TYPE_3D_RIGHT) {
+                               have_3d = true;
+                       }
+               } else if (dynamic_pointer_cast<TimelineSubtitleContentView> (i)) {
+                       have_subtitle = true;
+               } else if (dynamic_pointer_cast<TimelineAtmosContentView> (i)) {
+                       have_atmos = true;
+               }
+       }
+
+       _labels_view->set_3d (have_3d);
+       _labels_view->set_subtitle (have_subtitle);
+       _labels_view->set_atmos (have_atmos);
+
+       /* Hence decide where to start subtitle, atmos and audio tracks */
+       int const subtitle = have_3d ? 2 : 1;
+       int const atmos = have_subtitle ? subtitle + 1 : subtitle;
+       int const audio = have_atmos ? atmos + 1: atmos;
+
        for (TimelineViewList::iterator i = _views.begin(); i != _views.end(); ++i) {
                shared_ptr<TimelineContentView> cv = dynamic_pointer_cast<TimelineContentView> (*i);
                if (!cv) {
@@ -194,19 +230,21 @@ Timeline::assign_tracks ()
                }
 
                if (dynamic_pointer_cast<TimelineVideoContentView> (*i)) {
-                       /* Video on tracks 0 and 1 (left and right eye) */
+                       /* Video on tracks 0 and maybe 1 (left and right eye) */
                        cv->set_track (cv->content()->video->frame_type() == VIDEO_FRAME_TYPE_3D_RIGHT ? 1 : 0);
-                       _tracks = max (_tracks, 2);
+                       _tracks = max (_tracks, have_3d ? 2 : 1);
                        continue;
                } else if (dynamic_pointer_cast<TimelineSubtitleContentView> (*i)) {
-                       /* Subtitles on track 2 */
-                       cv->set_track (2);
-                       _tracks = max (_tracks, 3);
+                       cv->set_track (subtitle);
+                       _tracks = max (_tracks, subtitle + 1);
+                       continue;
+               } else if (dynamic_pointer_cast<TimelineAtmosContentView> (*i)) {
+                       cv->set_track (atmos);
+                       _tracks = max (_tracks, atmos + 1);
                        continue;
                }
 
-               /* Audio on tracks 3 and up */
-               int t = 3;
+               int t = audio;
 
                shared_ptr<Content> content = cv->content();
                DCPTimePeriod content_period (content->position(), content->end());
diff --git a/src/wx/timeline_atmos_content_view.cc b/src/wx/timeline_atmos_content_view.cc
new file mode 100644 (file)
index 0000000..893b57a
--- /dev/null
@@ -0,0 +1,44 @@
+/*
+    Copyright (C) 2016 Carl Hetherington <cth@carlh.net>
+
+    This program 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.
+
+    This program 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 this program; if not, write to the Free Software
+    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+*/
+
+#include "timeline_atmos_content_view.h"
+
+using boost::shared_ptr;
+
+/** @class TimelineAtmosContentView
+ *  @brief Timeline view for AtmosContent.
+ */
+
+TimelineAtmosContentView::TimelineAtmosContentView (Timeline& tl, shared_ptr<Content> c)
+       : TimelineContentView (tl, c)
+{
+
+}
+
+wxColour
+TimelineAtmosContentView::background_colour () const
+{
+       return wxColour (149, 121, 232, 255);
+}
+
+wxColour
+TimelineAtmosContentView::foreground_colour () const
+{
+       return wxColour (0, 0, 0, 255);
+}
diff --git a/src/wx/timeline_atmos_content_view.h b/src/wx/timeline_atmos_content_view.h
new file mode 100644 (file)
index 0000000..951dc82
--- /dev/null
@@ -0,0 +1,36 @@
+/*
+    Copyright (C) 2016 Carl Hetherington <cth@carlh.net>
+
+    This program 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.
+
+    This program 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 this program; if not, write to the Free Software
+    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+*/
+
+#include "timeline_content_view.h"
+
+/** @class TimelineAtmosContentView
+ *  @brief Timeline view for AtmosContent.
+ */
+class TimelineAtmosContentView : public TimelineContentView
+{
+public:
+       TimelineAtmosContentView (Timeline& tl, boost::shared_ptr<Content> c);
+
+private:
+       bool active () const {
+               return true;
+       }
+       wxColour background_colour () const;
+       wxColour foreground_colour () const;
+};
index 3a809bfffca3a991582f7cc89fcd03a18a7983b5..ee1b707183466a14f7c79a0601ff2ab4a0a4c2af 100644 (file)
@@ -29,11 +29,15 @@ using std::max;
 
 TimelineLabelsView::TimelineLabelsView (Timeline& tl)
        : TimelineView (tl)
+       , _threed (true)
+       , _subtitle (true)
+       , _atmos (true)
 {
        wxString labels[] = {
                _("Video"),
                _("Audio"),
-               _("Subtitles")
+               _("Subtitles"),
+               _("Atmos")
        };
 
        _width = 0;
@@ -58,7 +62,42 @@ TimelineLabelsView::do_paint (wxGraphicsContext* gc, list<dcpomatic::Rect<int> >
 {
        int const h = _timeline.track_height ();
        gc->SetFont (gc->CreateFont(wxNORMAL_FONT->Bold(), wxColour (0, 0, 0)));
-       gc->DrawText (_("Video"),     0, _timeline.tracks_position().y + h - 8);
-       gc->DrawText (_("Subtitles"), 0, _timeline.tracks_position().y + 5 * h / 2 - 8);
-       gc->DrawText (_("Audio"),     0, _timeline.tracks_position().y + (3 + max (_timeline.tracks(), 3)) * h / 2 - 8);
+
+       int fy = 0;
+       int ty = _threed ? 2 * h : h;
+       gc->DrawText (_("Video"),     0, _timeline.tracks_position().y + (ty + fy) / 2 - 8);
+       fy = ty;
+
+       if (_subtitle) {
+               ty = fy + h;
+               gc->DrawText (_("Subtitles"), 0, _timeline.tracks_position().y + (ty + fy) / 2 - 8);
+               fy = ty;
+       }
+
+       if (_atmos) {
+               ty = fy + h;
+               gc->DrawText (_("Atmos"), 0, _timeline.tracks_position().y + (ty + fy) / 2 - 8);
+               fy = ty;
+       }
+
+       ty = _timeline.tracks() * h;
+       gc->DrawText (_("Audio"), 0, _timeline.tracks_position().y + (ty + fy) / 2 - 8);
+}
+
+void
+TimelineLabelsView::set_3d (bool s)
+{
+       _threed = s;
+}
+
+void
+TimelineLabelsView::set_subtitle (bool s)
+{
+       _subtitle = s;
+}
+
+void
+TimelineLabelsView::set_atmos (bool s)
+{
+       _atmos = s;
 }
index 96dd692af344f60a9a128d376444f098b374c9d0..846184a92c0b127071de4c07b1e5a89a6f6eb2ef 100644 (file)
@@ -28,8 +28,15 @@ public:
 
        dcpomatic::Rect<int> bbox () const;
 
+       void set_3d (bool s);
+       void set_subtitle (bool s);
+       void set_atmos (bool s);
+
 private:
        void do_paint (wxGraphicsContext* gc, std::list<dcpomatic::Rect<int> > overlaps);
 
        int _width;
+       bool _threed;
+       bool _subtitle;
+       bool _atmos;
 };
index 19ff17d4e6707f77300f365c5572bf60b7b30f20..9a6538f4d043809eb07902a01ec60c03137d588c 100644 (file)
@@ -83,6 +83,7 @@ sources = """
           text_subtitle_appearance_dialog.cc
           timecode.cc
           timeline.cc
+          timeline_atmos_content_view.cc
           timeline_content_view.cc
           timeline_dialog.cc
           timeline_audio_content_view.cc