From 48e51965d74cf2a2f2f6f4c5e9c349f1b1103e66 Mon Sep 17 00:00:00 2001 From: Carl Hetherington Date: Wed, 25 May 2016 16:55:42 +0100 Subject: [PATCH] Basics of Atmos content support; can be added to project and appears in timeline. --- src/lib/atmos_mxf_content.cc | 92 +++++++++++++++++++++++++++ src/lib/atmos_mxf_content.h | 41 ++++++++++++ src/lib/content_factory.cc | 5 ++ src/lib/player.cc | 5 +- src/lib/wscript | 1 + src/wx/timeline.cc | 52 +++++++++++++-- src/wx/timeline_atmos_content_view.cc | 44 +++++++++++++ src/wx/timeline_atmos_content_view.h | 36 +++++++++++ src/wx/timeline_labels_view.cc | 47 ++++++++++++-- src/wx/timeline_labels_view.h | 7 ++ src/wx/wscript | 1 + 11 files changed, 319 insertions(+), 12 deletions(-) create mode 100644 src/lib/atmos_mxf_content.cc create mode 100644 src/lib/atmos_mxf_content.h create mode 100644 src/wx/timeline_atmos_content_view.cc create mode 100644 src/wx/timeline_atmos_content_view.h diff --git a/src/lib/atmos_mxf_content.cc b/src/lib/atmos_mxf_content.cc new file mode 100644 index 000000000..927d36ff6 --- /dev/null +++ b/src/lib/atmos_mxf_content.cc @@ -0,0 +1,92 @@ +/* + Copyright (C) 2016 Carl Hetherington + + 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 +#include +#include + +#include "i18n.h" + +using std::list; +using std::string; +using boost::shared_ptr; + +AtmosMXFContent::AtmosMXFContent (shared_ptr film, boost::filesystem::path path) + : Content (film, path) +{ + +} + +AtmosMXFContent::AtmosMXFContent (shared_ptr film, cxml::ConstNodePtr node, int) + : Content (film, node) +{ + +} + +bool +AtmosMXFContent::valid_mxf (boost::filesystem::path path) +{ + try { + shared_ptr a (new dcp::AtmosAsset (path)); + return true; + } catch (dcp::MXFFileError& e) { + + } catch (dcp::DCPReadError& e) { + + } + + return false; +} + +void +AtmosMXFContent::examine (shared_ptr job) +{ + job->set_progress_unknown (); + Content::examine (job); + shared_ptr 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 index 000000000..b03094823 --- /dev/null +++ b/src/lib/atmos_mxf_content.h @@ -0,0 +1,41 @@ +/* + Copyright (C) 2016 Carl Hetherington + + 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 film, boost::filesystem::path path); + AtmosMXFContent (boost::shared_ptr film, cxml::ConstNodePtr node, int version); + + boost::shared_ptr shared_from_this () { + return boost::dynamic_pointer_cast (Content::shared_from_this ()); + } + + void examine (boost::shared_ptr 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; +}; diff --git a/src/lib/content_factory.cc b/src/lib/content_factory.cc index 706c79754..df803809f 100644 --- a/src/lib/content_factory.cc +++ b/src/lib/content_factory.cc @@ -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 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 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) { diff --git a/src/lib/player.cc b/src/lib/player.cc index 0c513056c..6d155836f 100644 --- a/src/lib/player.cc +++ b/src/lib/player.cc @@ -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 (); diff --git a/src/lib/wscript b/src/lib/wscript index 727a398af..4c5ed04db 100644 --- a/src/lib/wscript +++ b/src/lib/wscript @@ -21,6 +21,7 @@ import i18n sources = """ analyse_audio_job.cc + atmos_mxf_content.cc audio_analysis.cc audio_buffers.cc audio_content.cc diff --git a/src/wx/timeline.cc b/src/wx/timeline.cc index 8ce811c28..2a0f96f05 100644 --- a/src/wx/timeline.cc +++ b/src/wx/timeline.cc @@ -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 #include #include @@ -157,6 +159,10 @@ Timeline::recreate_views () if (i->subtitle) { _views.push_back (shared_ptr (new TimelineSubtitleContentView (*this, i))); } + + if (dynamic_pointer_cast (i)) { + _views.push_back (shared_ptr (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 i, _views) { + shared_ptr cv = dynamic_pointer_cast (i); + if (!cv) { + continue; + } + + if (dynamic_pointer_cast (i)) { + if (cv->content()->video->frame_type() == VIDEO_FRAME_TYPE_3D_RIGHT) { + have_3d = true; + } + } else if (dynamic_pointer_cast (i)) { + have_subtitle = true; + } else if (dynamic_pointer_cast (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 cv = dynamic_pointer_cast (*i); if (!cv) { @@ -194,19 +230,21 @@ Timeline::assign_tracks () } if (dynamic_pointer_cast (*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 (*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 (*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 = 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 index 000000000..893b57a72 --- /dev/null +++ b/src/wx/timeline_atmos_content_view.cc @@ -0,0 +1,44 @@ +/* + Copyright (C) 2016 Carl Hetherington + + 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 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 index 000000000..951dc82cc --- /dev/null +++ b/src/wx/timeline_atmos_content_view.h @@ -0,0 +1,36 @@ +/* + Copyright (C) 2016 Carl Hetherington + + 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 c); + +private: + bool active () const { + return true; + } + wxColour background_colour () const; + wxColour foreground_colour () const; +}; diff --git a/src/wx/timeline_labels_view.cc b/src/wx/timeline_labels_view.cc index 3a809bfff..ee1b70718 100644 --- a/src/wx/timeline_labels_view.cc +++ b/src/wx/timeline_labels_view.cc @@ -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 > { 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; } diff --git a/src/wx/timeline_labels_view.h b/src/wx/timeline_labels_view.h index 96dd692af..846184a92 100644 --- a/src/wx/timeline_labels_view.h +++ b/src/wx/timeline_labels_view.h @@ -28,8 +28,15 @@ public: dcpomatic::Rect 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 > overlaps); int _width; + bool _threed; + bool _subtitle; + bool _atmos; }; diff --git a/src/wx/wscript b/src/wx/wscript index 19ff17d4e..9a6538f4d 100644 --- a/src/wx/wscript +++ b/src/wx/wscript @@ -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 -- 2.30.2