diff options
| author | Carl Hetherington <cth@carlh.net> | 2024-08-06 23:56:38 +0200 |
|---|---|---|
| committer | Carl Hetherington <cth@carlh.net> | 2024-08-17 12:57:31 +0200 |
| commit | c8128908da7db78a920452f43b531383bb14c115 (patch) | |
| tree | e06a72e9b38ddbc0de1bc86d28af0fbd96977b6d /src | |
| parent | f037f1cc035a1e81b582cfaba6087e693cca9a26 (diff) | |
Support open captions and closed subtitles.
Diffstat (limited to 'src')
| -rw-r--r-- | src/reel.cc | 113 | ||||
| -rw-r--r-- | src/reel.h | 10 | ||||
| -rw-r--r-- | src/reel_interop_text_asset.cc | 6 | ||||
| -rw-r--r-- | src/reel_smpte_text_asset.cc | 6 | ||||
| -rw-r--r-- | src/text_type.h | 2 |
5 files changed, 108 insertions, 29 deletions
diff --git a/src/reel.cc b/src/reel.cc index 6208f3a6..ce654f6f 100644 --- a/src/reel.cc +++ b/src/reel.cc @@ -90,12 +90,23 @@ Reel::Reel (std::shared_ptr<const cxml::Node> node, dcp::Standard standard) if (auto main_subtitle = asset_list->optional_node_child("MainSubtitle")) { switch (standard) { - case Standard::INTEROP: - _main_subtitle = make_shared<ReelInteropTextAsset>(main_subtitle); - break; - case Standard::SMPTE: - _main_subtitle = make_shared<ReelSMPTETextAsset>(main_subtitle); - break; + case Standard::INTEROP: + _main_subtitle = make_shared<ReelInteropTextAsset>(main_subtitle); + break; + case Standard::SMPTE: + _main_subtitle = make_shared<ReelSMPTETextAsset>(main_subtitle); + break; + } + } + + if (auto main_caption = asset_list->optional_node_child("MainCaption")) { + switch (standard) { + case Standard::INTEROP: + DCP_ASSERT(false); + break; + case Standard::SMPTE: + _main_caption = make_shared<ReelSMPTETextAsset>(main_caption); + break; } } @@ -103,6 +114,18 @@ Reel::Reel (std::shared_ptr<const cxml::Node> node, dcp::Standard standard) _main_markers = make_shared<ReelMarkersAsset>(main_markers); } + auto closed_subtitles = asset_list->node_children("ClosedSubtitle"); + for (auto i: closed_subtitles) { + switch (standard) { + case Standard::INTEROP: + DCP_ASSERT(false); + break; + case Standard::SMPTE: + _closed_subtitles.push_back(make_shared<ReelSMPTETextAsset>(i)); + break; + } + } + /* XXX: it's not ideal that we silently tolerate Interop or SMPTE nodes here */ /* XXX: not sure if Interop supports multiple closed captions */ auto closed_captions = asset_list->node_children ("MainClosedCaption"); @@ -111,12 +134,12 @@ Reel::Reel (std::shared_ptr<const cxml::Node> node, dcp::Standard standard) } for (auto i: closed_captions) { switch (standard) { - case Standard::INTEROP: - _closed_captions.push_back (make_shared<ReelInteropTextAsset>(i)); - break; - case Standard::SMPTE: - _closed_captions.push_back (make_shared<ReelSMPTETextAsset>(i)); - break; + case Standard::INTEROP: + _closed_captions.push_back(make_shared<ReelInteropTextAsset>(i)); + break; + case Standard::SMPTE: + _closed_captions.push_back(make_shared<ReelSMPTETextAsset>(i)); + break; } } @@ -153,6 +176,14 @@ Reel::write_to_cpl (xmlpp::Element* node, Standard standard) const _main_subtitle->write_to_cpl (asset_list, standard); } + if (_main_caption) { + _main_caption->write_to_cpl(asset_list, standard); + } + + for (auto i: _closed_subtitles) { + i->write_to_cpl(asset_list, standard); + } + for (auto i: _closed_captions) { i->write_to_cpl (asset_list, standard); } @@ -350,10 +381,19 @@ Reel::add (shared_ptr<ReelAsset> asset) } else if (auto so = dynamic_pointer_cast<ReelSoundAsset>(asset)) { _main_sound = so; } else if (auto te = dynamic_pointer_cast<ReelTextAsset>(asset)) { - if (te->type() == TextType::OPEN_SUBTITLE) { + switch (te->type()) { + case TextType::OPEN_SUBTITLE: _main_subtitle = te; - } else { + break; + case TextType::OPEN_CAPTION: + _main_caption = te; + break; + case TextType::CLOSED_SUBTITLE: + _closed_subtitles.push_back(te); + break; + case TextType::CLOSED_CAPTION: _closed_captions.push_back(te); + break; } } else if (auto m = dynamic_pointer_cast<ReelMarkersAsset>(asset)) { _main_markers = m; @@ -378,6 +418,10 @@ Reel::assets () const if (_main_subtitle) { a.push_back (_main_subtitle); } + if (_main_caption) { + a.push_back(_main_caption); + } + std::copy (_closed_subtitles.begin(), _closed_subtitles.end(), back_inserter(a)); std::copy (_closed_captions.begin(), _closed_captions.end(), back_inserter(a)); if (_atmos) { a.push_back (_atmos); @@ -397,28 +441,33 @@ Reel::resolve_refs (vector<shared_ptr<Asset>> assets) _main_sound->asset_ref().resolve(assets); } - if (_main_subtitle) { - _main_subtitle->asset_ref().resolve(assets); - + auto resolve_interop_fonts = [&assets](shared_ptr<ReelTextAsset>(asset)) { /* Interop subtitle handling is all special cases */ - if (_main_subtitle->asset_ref().resolved()) { - auto iop = dynamic_pointer_cast<InteropTextAsset>(_main_subtitle->asset_ref().asset()); - if (iop) { - iop->resolve_fonts (assets); + if (asset->asset_ref().resolved()) { + if (auto iop = dynamic_pointer_cast<InteropTextAsset>(asset->asset_ref().asset())) { + iop->resolve_fonts(assets); } } + + }; + + if (_main_subtitle) { + _main_subtitle->asset_ref().resolve(assets); + resolve_interop_fonts(_main_subtitle); } - for (auto i: _closed_captions) { + if (_main_caption) { + _main_caption->asset_ref().resolve(assets); + } + + for (auto i: _closed_subtitles) { i->asset_ref().resolve(assets); + resolve_interop_fonts(i); + } - /* Interop subtitle handling is all special cases */ - if (i->asset_ref().resolved()) { - auto iop = dynamic_pointer_cast<InteropTextAsset>(i->asset_ref().asset()); - if (iop) { - iop->resolve_fonts (assets); - } - } + for (auto i: _closed_captions) { + i->asset_ref().resolve(assets); + resolve_interop_fonts(i); } if (_atmos) { @@ -446,9 +495,15 @@ Reel::duration () const if (_main_subtitle) { d = min (d, _main_subtitle->actual_duration()); } + if (_main_caption) { + d = min(d, _main_caption->actual_duration()); + } if (_main_markers) { d = min (d, _main_markers->actual_duration()); } + for (auto i: _closed_subtitles) { + d = min(d, i->actual_duration()); + } for (auto i: _closed_captions) { d = min (d, i->actual_duration()); } @@ -109,10 +109,18 @@ public: return _main_subtitle; } + std::shared_ptr<ReelTextAsset> main_caption() const { + return _main_caption; + } + std::shared_ptr<ReelMarkersAsset> main_markers () const { return _main_markers; } + std::vector<std::shared_ptr<ReelTextAsset>> closed_subtitles() const { + return _closed_subtitles; + } + std::vector<std::shared_ptr<ReelTextAsset>> closed_captions () const { return _closed_captions; } @@ -146,7 +154,9 @@ private: std::shared_ptr<ReelPictureAsset> _main_picture; std::shared_ptr<ReelSoundAsset> _main_sound; std::shared_ptr<ReelTextAsset> _main_subtitle; + std::shared_ptr<ReelTextAsset> _main_caption; std::shared_ptr<ReelMarkersAsset> _main_markers; + std::vector<std::shared_ptr<ReelTextAsset>> _closed_subtitles; std::vector<std::shared_ptr<ReelTextAsset>> _closed_captions; std::shared_ptr<ReelAtmosAsset> _atmos; diff --git a/src/reel_interop_text_asset.cc b/src/reel_interop_text_asset.cc index c43cf37b..0f99b614 100644 --- a/src/reel_interop_text_asset.cc +++ b/src/reel_interop_text_asset.cc @@ -72,6 +72,10 @@ ReelInteropTextAsset::cpl_node_name() const switch (_type) { case TextType::OPEN_SUBTITLE: return "MainSubtitle"; + case TextType::OPEN_CAPTION: + return "cc-cpl:MainCaption"; + case TextType::CLOSED_SUBTITLE: + return "ClosedSubtitle"; case TextType::CLOSED_CAPTION: return "cc-cpl:MainClosedCaption"; } @@ -86,7 +90,9 @@ ReelInteropTextAsset::cpl_node_namespace() const { switch (_type) { case TextType::OPEN_SUBTITLE: + case TextType::CLOSED_SUBTITLE: return {}; + case TextType::OPEN_CAPTION: case TextType::CLOSED_CAPTION: return make_pair("http://www.digicine.com/PROTO-ASDCP-CC-CPL-20070926#", "cc-cpl"); } diff --git a/src/reel_smpte_text_asset.cc b/src/reel_smpte_text_asset.cc index 7950dfd2..b1ce34cb 100644 --- a/src/reel_smpte_text_asset.cc +++ b/src/reel_smpte_text_asset.cc @@ -74,6 +74,10 @@ ReelSMPTETextAsset::cpl_node_name() const switch (_type) { case TextType::OPEN_SUBTITLE: return "MainSubtitle"; + case TextType::OPEN_CAPTION: + return "tt:MainCaption"; + case TextType::CLOSED_SUBTITLE: + return "ClosedSubtitle"; case TextType::CLOSED_CAPTION: return "tt:ClosedCaption"; } @@ -88,7 +92,9 @@ ReelSMPTETextAsset::cpl_node_namespace() const { switch (_type) { case TextType::OPEN_SUBTITLE: + case TextType::CLOSED_SUBTITLE: return {}; + case TextType::OPEN_CAPTION: case TextType::CLOSED_CAPTION: return make_pair("http://www.smpte-ra.org/schemas/429-12/2008/TT", "tt"); } diff --git a/src/text_type.h b/src/text_type.h index 3f4f43c8..60065478 100644 --- a/src/text_type.h +++ b/src/text_type.h @@ -38,6 +38,8 @@ namespace dcp { enum class TextType { OPEN_SUBTITLE, + OPEN_CAPTION, + CLOSED_SUBTITLE, CLOSED_CAPTION }; |
